M2.875 · Deep Learning · PEC1
2022-2 · Máster universitario en Ciencia de datos (Data science)
Estudios de Informática, Multimedia y Telecomunicación
A lo largo de esta práctica vamos a implementar varios modelos de redes neuronales para clasificar las imágenes de una base de datos de imágenes satelitales. En concreto:
Consideraciones generales:
Formato de la entrega:
Las imágenes tomadas por satélite son clave en la supervisión del uso y la cobertura del suelo, cuestiones relevantes para la gestión ambiental, la planificación urbana, la sostenibilidad y para combatir el cambio climático.
En esta práctica, trabajaremos con la base de datos UC Merced Land Use Data, que consiste en imágenes satelitales de 256x256 píxeles de 21 escenas diferentes: las clases son diversas, conteniendo escenas e imágenes de aviones o ríos, entre otras categorías.
Concretamente trabajaremos con una versión aumentada de dicha base de datos que está disponible en un repositorio de Kaggle. En esta versión se han llevado a cabo varios procesos de aumentación de datos de tal forma que el número de imágenes por clase pasa de 100 a 500.
Nota: Se recomienda realizar la práctica en el entorno que ofrece la plataforma Kaggle, ya que ofrece un entorno gratuito con 30 horas semanales de uso de GPU.
A lo largo de toda la práctica, para la creación de las distintas redes, iremos alternando el uso del modelo Sequential y el modelo Functional de Keras a través de las clases Sequential y Model respectivamente.
Empezamos cargando las librerías mas relevantes:
# Importamos tensorflow
import tensorflow as tf
print("TF version : ", tf.__version__)
# Necesitaremos GPU
print("GPU available: ", tf.config.list_physical_devices('GPU'))
# keras version is 2.11.0
import keras
print("Keras version : ", keras.__version__)
TF version : 2.11.0 GPU available: [PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')] Keras version : 2.11.0
# Importamos los elementos de keras que utilizaremos con mayor frecuencia
from keras.utils import image_dataset_from_directory
from keras.layers import (
GlobalAveragePooling2D, Flatten, Input,
Dense, Dropout, Conv2D, Conv2DTranspose, BatchNormalization,
MaxPooling2D, UpSampling2D, Rescaling, Resizing)
from keras.callbacks import EarlyStopping
from keras.optimizers import Adam
from keras import Sequential, Model
from tensorflow.keras import layers
# Importamos el resto de librerías que necesitaremos para la PEC
import cv2
import glob
import os
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import time
En este apartado exploraremos la base de datos y prepararemos la carga de las imágenes para los modelos de los siguientes apartados.
Para la descarga de la base de datos tenemos 2 opciones dependiendo de si decidimos trabajar en local o desde el entorno de Kaggle:
../input/.Una vez tenemos la base de datos accesible vamos a inspeccionarla.
Las imágenes se encuentran agrupadas de 2 formas diferentes:
/landuse-scene-classification/images/ se encuentra el total de las imágenes separadas por clases (cada clase en una carpeta distinta). Pero no se ha realizado una separación en conjunto de entrenamiento y test (o entrenamiento, validación y test)./landuse-scene-classification/images_train_test_val/ se encuentran 3 carpetas (test, train y validation) en las que el total de imágenes se ha separado de forma aleatoria. En cada una de las 3 carpetas, tenemos imágenes de las 21 clases agrupadas en sus correspondientes carpetas. En la carpeta raíz /landuse-scene-classification/ tenemos 3 archivos .csv con la distribución de cada carpeta.En esta práctica utilizaremos el dataset ya particionado, es decir, trabajaremos con las imágenes que se encuentran en la ruta /landuse-scene-classification/images_train_test_val/.
A partir de los archivos .csv podemos ver cómo se han distribuído los datos. Por ejemplo:
train = pd.read_csv('../input/landuse-scene-classification/train.csv')
train.head(5)
| Unnamed: 0 | Filename | Label | ClassName | |
|---|---|---|---|---|
| 0 | 5818 | runway/runway_000259.png | 16 | runway |
| 1 | 1327 | intersection/intersection_000348.png | 10 | intersection |
| 2 | 2529 | agricultural/agricultural_000025.png | 0 | agricultural |
| 3 | 3865 | chaparral/chaparral_000195.png | 5 | chaparral |
| 4 | 2024 | airplane/airplane_000260.png | 1 | airplane |
test = pd.read_csv('../input/landuse-scene-classification/test.csv')
test.head(5)
| Unnamed: 0 | Filename | Label | ClassName | |
|---|---|---|---|---|
| 0 | 311 | river/river_000149.png | 15 | river |
| 1 | 975 | mediumresidential/mediumresidential_000335.png | 11 | mediumresidential |
| 2 | 547 | overpass/overpass_000338.png | 13 | overpass |
| 3 | 670 | storagetanks/storagetanks_000307.png | 18 | storagetanks |
| 4 | 330 | river/river_000370.png | 15 | river |
validation = pd.read_csv('../input/landuse-scene-classification/validation.csv')
validation.head(5)
| Unnamed: 0 | Filename | Label | ClassName | |
|---|---|---|---|---|
| 0 | 1928 | mediumresidential/mediumresidential_000305.png | 11 | mediumresidential |
| 1 | 102 | buildings/buildings_000191.png | 4 | buildings |
| 2 | 823 | tenniscourt/tenniscourt_000224.png | 19 | tenniscourt |
| 3 | 2083 | denseresidential/denseresidential_000436.png | 6 | denseresidential |
| 4 | 1579 | baseballdiamond/baseballdiamond_000280.png | 2 | baseballdiamond |
# Extraer nombres de las clases
nombres = train['ClassName'].unique()
print(nombres)
['runway' 'intersection' 'agricultural' 'chaparral' 'airplane' 'storagetanks' 'tenniscourt' 'overpass' 'harbor' 'buildings' 'mediumresidential' 'baseballdiamond' 'golfcourse' 'freeway' 'sparseresidential' 'river' 'mobilehomepark' 'forest' 'beach' 'parkinglot' 'denseresidential']
# Número de instancias por conjunto
conteo_instancias_train = train.shape[0]
conteo_instancias_test = test.shape[0]
conteo_instancias_validation = validation.shape[0]
print("\n\n=======\nTRAIN\n=======\n" ,conteo_instancias_train)
print("\n\n=====\nTEST\n=====\n",conteo_instancias_test)
print("\n\n==========\nVALIDATION\n==========\n",conteo_instancias_validation)
======= TRAIN ======= 7350 ===== TEST ===== 1050 ========== VALIDATION ========== 2100
# Número de instancias por clase
conteo_instancias_Clase_train = train['ClassName'].value_counts()
conteo_instancias_Clase_test = test['ClassName'].value_counts()
conteo_instancias_Clase_validation = validation['ClassName'].value_counts()
print("\n\n==========================\nTRAIN\n==========================\n" ,conteo_instancias_Clase_train)
print("\n\n==========================\nTEST\n==========================\n",conteo_instancias_Clase_test)
print("\n\n==========================\nVALIDATION\n==========================\n",conteo_instancias_Clase_validation)
========================== TRAIN ========================== runway 350 baseballdiamond 350 parkinglot 350 beach 350 forest 350 mobilehomepark 350 river 350 sparseresidential 350 freeway 350 golfcourse 350 mediumresidential 350 intersection 350 buildings 350 harbor 350 overpass 350 tenniscourt 350 storagetanks 350 airplane 350 chaparral 350 agricultural 350 denseresidential 350 Name: ClassName, dtype: int64 ========================== TEST ========================== river 50 airplane 50 baseballdiamond 50 agricultural 50 parkinglot 50 freeway 50 sparseresidential 50 mobilehomepark 50 forest 50 intersection 50 runway 50 mediumresidential 50 beach 50 denseresidential 50 buildings 50 tenniscourt 50 chaparral 50 golfcourse 50 storagetanks 50 overpass 50 harbor 50 Name: ClassName, dtype: int64 ========================== VALIDATION ========================== mediumresidential 100 runway 100 sparseresidential 100 golfcourse 100 chaparral 100 storagetanks 100 airplane 100 freeway 100 beach 100 forest 100 mobilehomepark 100 buildings 100 overpass 100 river 100 parkinglot 100 harbor 100 intersection 100 baseballdiamond 100 denseresidential 100 tenniscourt 100 agricultural 100 Name: ClassName, dtype: int64
Aunque se supone que cada archivo .csv refleja a la perfección el contenido de cada conjunto de datos, no está demás cerciorarse que el contenido del mismo se corresponde con lo anotado en cada archivo. Para ello se pide:
# Para el conjunto de datos de entrenamiento
print("\n\n==========================\nTRAIN\n==========================\n")
for conjunto in ['/kaggle/input/landuse-scene-classification/images_train_test_val/train/']:
for categoria in train['ClassName'].unique():
carpeta = os.path.join(conjunto, categoria)
cantidad_imagenes = len(os.listdir(carpeta))
print("La Categoría:",categoria, "tiene:", cantidad_imagenes, "imágenes")
========================== TRAIN ========================== La Categoría: runway tiene: 350 imágenes La Categoría: intersection tiene: 350 imágenes La Categoría: agricultural tiene: 350 imágenes La Categoría: chaparral tiene: 350 imágenes La Categoría: airplane tiene: 350 imágenes La Categoría: storagetanks tiene: 350 imágenes La Categoría: tenniscourt tiene: 350 imágenes La Categoría: overpass tiene: 350 imágenes La Categoría: harbor tiene: 350 imágenes La Categoría: buildings tiene: 350 imágenes La Categoría: mediumresidential tiene: 350 imágenes La Categoría: baseballdiamond tiene: 350 imágenes La Categoría: golfcourse tiene: 350 imágenes La Categoría: freeway tiene: 350 imágenes La Categoría: sparseresidential tiene: 350 imágenes La Categoría: river tiene: 350 imágenes La Categoría: mobilehomepark tiene: 350 imágenes La Categoría: forest tiene: 350 imágenes La Categoría: beach tiene: 350 imágenes La Categoría: parkinglot tiene: 350 imágenes La Categoría: denseresidential tiene: 350 imágenes
for categoria in train['ClassName'].unique():
carpeta = os.path.join('/kaggle/input/landuse-scene-classification/images_train_test_val/train/', categoria)
archivo_imagen = os.listdir(carpeta)[0]
ruta_imagen = os.path.join(carpeta, archivo_imagen)
print(ruta_imagen)
imagen = cv2.imread(ruta_imagen)
plt.imshow(imagen)
plt.title(categoria)
plt.axis('off')
plt.show()
/kaggle/input/landuse-scene-classification/images_train_test_val/train/runway/runway_000495.png
/kaggle/input/landuse-scene-classification/images_train_test_val/train/intersection/intersection_000175.png
/kaggle/input/landuse-scene-classification/images_train_test_val/train/agricultural/agricultural_000139.png
/kaggle/input/landuse-scene-classification/images_train_test_val/train/chaparral/chaparral_000278.png
/kaggle/input/landuse-scene-classification/images_train_test_val/train/airplane/airplane_000482.png
/kaggle/input/landuse-scene-classification/images_train_test_val/train/storagetanks/storagetanks_000207.png
/kaggle/input/landuse-scene-classification/images_train_test_val/train/tenniscourt/tenniscourt_000271.png
/kaggle/input/landuse-scene-classification/images_train_test_val/train/overpass/overpass_000400.png
/kaggle/input/landuse-scene-classification/images_train_test_val/train/harbor/harbor_000183.png
/kaggle/input/landuse-scene-classification/images_train_test_val/train/buildings/buildings_000224.png
/kaggle/input/landuse-scene-classification/images_train_test_val/train/mediumresidential/mediumresidential_000485.png
/kaggle/input/landuse-scene-classification/images_train_test_val/train/baseballdiamond/baseballdiamond_000048.png
/kaggle/input/landuse-scene-classification/images_train_test_val/train/golfcourse/golfcourse_000289.png
/kaggle/input/landuse-scene-classification/images_train_test_val/train/freeway/freeway_000431.png
/kaggle/input/landuse-scene-classification/images_train_test_val/train/sparseresidential/sparseresidential_000222.png
/kaggle/input/landuse-scene-classification/images_train_test_val/train/river/river_000378.png
/kaggle/input/landuse-scene-classification/images_train_test_val/train/mobilehomepark/mobilehomepark_000126.png
/kaggle/input/landuse-scene-classification/images_train_test_val/train/forest/forest_000055.png
/kaggle/input/landuse-scene-classification/images_train_test_val/train/beach/beach_000368.png
/kaggle/input/landuse-scene-classification/images_train_test_val/train/parkinglot/parkinglot_000156.png
/kaggle/input/landuse-scene-classification/images_train_test_val/train/denseresidential/denseresidential_000001.png
print("\n\n==========================\nTRAIN\n==========================\n")
for categoria in train['ClassName'].unique():
carpeta = os.path.join('/kaggle/input/landuse-scene-classification/images_train_test_val/train/', categoria)
archivo_imagen = os.listdir(carpeta)[0]
ruta_imagen = os.path.join(carpeta, archivo_imagen)
imagen = cv2.imread(ruta_imagen)
rango_min = np.min(imagen)
rango_max = np.max(imagen)
print("La Categoría:",categoria, "tiene un rango dinámico de entre:", rango_min, "y" ,rango_max)
========================== TRAIN ========================== La Categoría: runway tiene un rango dinámico de entre: 1 y 255 La Categoría: intersection tiene un rango dinámico de entre: 0 y 255 La Categoría: agricultural tiene un rango dinámico de entre: 0 y 211 La Categoría: chaparral tiene un rango dinámico de entre: 27 y 255 La Categoría: airplane tiene un rango dinámico de entre: 0 y 206 La Categoría: storagetanks tiene un rango dinámico de entre: 0 y 248 La Categoría: tenniscourt tiene un rango dinámico de entre: 0 y 255 La Categoría: overpass tiene un rango dinámico de entre: 12 y 255 La Categoría: harbor tiene un rango dinámico de entre: 0 y 255 La Categoría: buildings tiene un rango dinámico de entre: 0 y 255 La Categoría: mediumresidential tiene un rango dinámico de entre: 0 y 233 La Categoría: baseballdiamond tiene un rango dinámico de entre: 0 y 250 La Categoría: golfcourse tiene un rango dinámico de entre: 0 y 255 La Categoría: freeway tiene un rango dinámico de entre: 0 y 219 La Categoría: sparseresidential tiene un rango dinámico de entre: 1 y 255 La Categoría: river tiene un rango dinámico de entre: 0 y 247 La Categoría: mobilehomepark tiene un rango dinámico de entre: 29 y 255 La Categoría: forest tiene un rango dinámico de entre: 0 y 255 La Categoría: beach tiene un rango dinámico de entre: 24 y 215 La Categoría: parkinglot tiene un rango dinámico de entre: 0 y 255 La Categoría: denseresidential tiene un rango dinámico de entre: 0 y 255
# Para el conjunto de datos de validación
print("\n\n==========================\nVALIDATION\n==========================\n")
for conjunto in ['/kaggle/input/landuse-scene-classification/images_train_test_val/validation/']:
for categoria in validation['ClassName'].unique():
carpeta = os.path.join(conjunto, categoria)
cantidad_imagenes = len(os.listdir(carpeta))
print("La Categoría:",categoria, "tiene:", cantidad_imagenes, "imágenes")
========================== VALIDATION ========================== La Categoría: mediumresidential tiene: 100 imágenes La Categoría: buildings tiene: 100 imágenes La Categoría: tenniscourt tiene: 100 imágenes La Categoría: denseresidential tiene: 100 imágenes La Categoría: baseballdiamond tiene: 100 imágenes La Categoría: intersection tiene: 100 imágenes La Categoría: harbor tiene: 100 imágenes La Categoría: parkinglot tiene: 100 imágenes La Categoría: river tiene: 100 imágenes La Categoría: overpass tiene: 100 imágenes La Categoría: mobilehomepark tiene: 100 imágenes La Categoría: runway tiene: 100 imágenes La Categoría: forest tiene: 100 imágenes La Categoría: beach tiene: 100 imágenes La Categoría: freeway tiene: 100 imágenes La Categoría: airplane tiene: 100 imágenes La Categoría: storagetanks tiene: 100 imágenes La Categoría: chaparral tiene: 100 imágenes La Categoría: golfcourse tiene: 100 imágenes La Categoría: sparseresidential tiene: 100 imágenes La Categoría: agricultural tiene: 100 imágenes
for categoria in validation['ClassName'].unique():
carpeta = os.path.join('/kaggle/input/landuse-scene-classification/images_train_test_val/validation/', categoria)
archivo_imagen = os.listdir(carpeta)[0]
ruta_imagen = os.path.join(carpeta, archivo_imagen)
print(ruta_imagen)
imagen = cv2.imread(ruta_imagen)
plt.imshow(imagen)
plt.title(categoria)
plt.axis('off')
plt.show()
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/mediumresidential/mediumresidential_000148.png
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/buildings/buildings_000445.png
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/tenniscourt/tenniscourt_000136.png
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/denseresidential/denseresidential_000424.png
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/baseballdiamond/baseballdiamond_000367.png
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/intersection/intersection_000072.png
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/harbor/harbor_000187.png
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/parkinglot/parkinglot_000140.png
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/river/river_000489.png
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/overpass/overpass_000150.png
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/mobilehomepark/mobilehomepark_000066.png
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/runway/runway_000479.png
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/forest/forest_000255.png
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/beach/beach_000362.png
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/freeway/freeway_000185.png
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/airplane/airplane_000293.png
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/storagetanks/storagetanks_000235.png
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/chaparral/chaparral_000441.png
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/golfcourse/golfcourse_000300.png
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/sparseresidential/sparseresidential_000182.png
/kaggle/input/landuse-scene-classification/images_train_test_val/validation/agricultural/agricultural_000037.png
print("\n\n==========================\nVALIDATION\n==========================\n")
for categoria in validation['ClassName'].unique():
carpeta = os.path.join('/kaggle/input/landuse-scene-classification/images_train_test_val/validation/', categoria)
archivo_imagen = os.listdir(carpeta)[0]
ruta_imagen = os.path.join(carpeta, archivo_imagen)
imagen = cv2.imread(ruta_imagen)
rango_min = np.min(imagen)
rango_max = np.max(imagen)
print("La Categoría:",categoria, "tiene un rango dinámico de entre:", rango_min, "y" ,rango_max)
========================== VALIDATION ========================== La Categoría: mediumresidential tiene un rango dinámico de entre: 12 y 255 La Categoría: buildings tiene un rango dinámico de entre: 0 y 203 La Categoría: tenniscourt tiene un rango dinámico de entre: 0 y 255 La Categoría: denseresidential tiene un rango dinámico de entre: 0 y 240 La Categoría: baseballdiamond tiene un rango dinámico de entre: 15 y 255 La Categoría: intersection tiene un rango dinámico de entre: 0 y 255 La Categoría: harbor tiene un rango dinámico de entre: 0 y 255 La Categoría: parkinglot tiene un rango dinámico de entre: 0 y 255 La Categoría: river tiene un rango dinámico de entre: 23 y 255 La Categoría: overpass tiene un rango dinámico de entre: 0 y 206 La Categoría: mobilehomepark tiene un rango dinámico de entre: 0 y 247 La Categoría: runway tiene un rango dinámico de entre: 0 y 255 La Categoría: forest tiene un rango dinámico de entre: 0 y 213 La Categoría: beach tiene un rango dinámico de entre: 18 y 235 La Categoría: freeway tiene un rango dinámico de entre: 14 y 255 La Categoría: airplane tiene un rango dinámico de entre: 12 y 255 La Categoría: storagetanks tiene un rango dinámico de entre: 0 y 255 La Categoría: chaparral tiene un rango dinámico de entre: 0 y 250 La Categoría: golfcourse tiene un rango dinámico de entre: 19 y 255 La Categoría: sparseresidential tiene un rango dinámico de entre: 0 y 220 La Categoría: agricultural tiene un rango dinámico de entre: 0 y 226
# Para el conjunto de datos de test
print("\n\n==========================\nTEST\n==========================\n")
for conjunto in ['/kaggle/input/landuse-scene-classification/images_train_test_val/test/']:
for categoria in test['ClassName'].unique():
carpeta = os.path.join(conjunto, categoria)
cantidad_imagenes = len(os.listdir(carpeta))
print("La Categoría:",categoria, "tiene:", cantidad_imagenes, "imágenes")
========================== TEST ========================== La Categoría: river tiene: 50 imágenes La Categoría: mediumresidential tiene: 50 imágenes La Categoría: overpass tiene: 50 imágenes La Categoría: storagetanks tiene: 50 imágenes La Categoría: golfcourse tiene: 50 imágenes La Categoría: chaparral tiene: 50 imágenes La Categoría: tenniscourt tiene: 50 imágenes La Categoría: buildings tiene: 50 imágenes La Categoría: denseresidential tiene: 50 imágenes La Categoría: beach tiene: 50 imágenes La Categoría: runway tiene: 50 imágenes La Categoría: airplane tiene: 50 imágenes La Categoría: intersection tiene: 50 imágenes La Categoría: forest tiene: 50 imágenes La Categoría: mobilehomepark tiene: 50 imágenes La Categoría: sparseresidential tiene: 50 imágenes La Categoría: freeway tiene: 50 imágenes La Categoría: parkinglot tiene: 50 imágenes La Categoría: agricultural tiene: 50 imágenes La Categoría: baseballdiamond tiene: 50 imágenes La Categoría: harbor tiene: 50 imágenes
for categoria in test['ClassName'].unique():
carpeta = os.path.join('/kaggle/input/landuse-scene-classification/images_train_test_val/test/', categoria)
archivo_imagen = os.listdir(carpeta)[0]
ruta_imagen = os.path.join(carpeta, archivo_imagen)
print(ruta_imagen)
imagen = cv2.imread(ruta_imagen)
plt.imshow(imagen)
plt.title(categoria)
plt.axis('off')
plt.show()
/kaggle/input/landuse-scene-classification/images_train_test_val/test/river/river_000133.png
/kaggle/input/landuse-scene-classification/images_train_test_val/test/mediumresidential/mediumresidential_000070.png
/kaggle/input/landuse-scene-classification/images_train_test_val/test/overpass/overpass_000444.png
/kaggle/input/landuse-scene-classification/images_train_test_val/test/storagetanks/storagetanks_000409.png
/kaggle/input/landuse-scene-classification/images_train_test_val/test/golfcourse/golfcourse_000120.png
/kaggle/input/landuse-scene-classification/images_train_test_val/test/chaparral/chaparral_000280.png
/kaggle/input/landuse-scene-classification/images_train_test_val/test/tenniscourt/tenniscourt_000356.png
/kaggle/input/landuse-scene-classification/images_train_test_val/test/buildings/buildings_000338.png
/kaggle/input/landuse-scene-classification/images_train_test_val/test/denseresidential/denseresidential_000254.png
/kaggle/input/landuse-scene-classification/images_train_test_val/test/beach/beach_000357.png
/kaggle/input/landuse-scene-classification/images_train_test_val/test/runway/runway_000105.png
/kaggle/input/landuse-scene-classification/images_train_test_val/test/airplane/airplane_000058.png
/kaggle/input/landuse-scene-classification/images_train_test_val/test/intersection/intersection_000371.png
/kaggle/input/landuse-scene-classification/images_train_test_val/test/forest/forest_000247.png
/kaggle/input/landuse-scene-classification/images_train_test_val/test/mobilehomepark/mobilehomepark_000317.png
/kaggle/input/landuse-scene-classification/images_train_test_val/test/sparseresidential/sparseresidential_000412.png
/kaggle/input/landuse-scene-classification/images_train_test_val/test/freeway/freeway_000434.png
/kaggle/input/landuse-scene-classification/images_train_test_val/test/parkinglot/parkinglot_000042.png
/kaggle/input/landuse-scene-classification/images_train_test_val/test/agricultural/agricultural_000033.png
/kaggle/input/landuse-scene-classification/images_train_test_val/test/baseballdiamond/baseballdiamond_000033.png
/kaggle/input/landuse-scene-classification/images_train_test_val/test/harbor/harbor_000418.png
print("\n\n==========================\nTEST\n==========================\n")
for categoria in test['ClassName'].unique():
carpeta = os.path.join('/kaggle/input/landuse-scene-classification/images_train_test_val/test/', categoria)
archivo_imagen = os.listdir(carpeta)[0]
ruta_imagen = os.path.join(carpeta, archivo_imagen)
imagen = cv2.imread(ruta_imagen)
rango_min = np.min(imagen)
rango_max = np.max(imagen)
print("La Categoría:",categoria, "tiene un rango dinámico de entre:", rango_min, "y" ,rango_max)
========================== TEST ========================== La Categoría: river tiene un rango dinámico de entre: 0 y 232 La Categoría: mediumresidential tiene un rango dinámico de entre: 0 y 245 La Categoría: overpass tiene un rango dinámico de entre: 0 y 255 La Categoría: storagetanks tiene un rango dinámico de entre: 0 y 255 La Categoría: golfcourse tiene un rango dinámico de entre: 36 y 255 La Categoría: chaparral tiene un rango dinámico de entre: 0 y 221 La Categoría: tenniscourt tiene un rango dinámico de entre: 0 y 255 La Categoría: buildings tiene un rango dinámico de entre: 0 y 255 La Categoría: denseresidential tiene un rango dinámico de entre: 0 y 244 La Categoría: beach tiene un rango dinámico de entre: 13 y 224 La Categoría: runway tiene un rango dinámico de entre: 24 y 255 La Categoría: airplane tiene un rango dinámico de entre: 0 y 251 La Categoría: intersection tiene un rango dinámico de entre: 0 y 255 La Categoría: forest tiene un rango dinámico de entre: 23 y 188 La Categoría: mobilehomepark tiene un rango dinámico de entre: 0 y 255 La Categoría: sparseresidential tiene un rango dinámico de entre: 0 y 250 La Categoría: freeway tiene un rango dinámico de entre: 0 y 220 La Categoría: parkinglot tiene un rango dinámico de entre: 20 y 234 La Categoría: agricultural tiene un rango dinámico de entre: 0 y 195 La Categoría: baseballdiamond tiene un rango dinámico de entre: 0 y 228 La Categoría: harbor tiene un rango dinámico de entre: 0 y 255
Con el objetivo de crear una base de datos en el formato Keras/Tensorflow a partir de las imágenes proporcionadas utilizaremos la función **tf.keras.utils.image_dataset_from_directory()** ya que nos permite crear bases de datos a partir de imágenes guardadas en carpetas.
La documentación de esta función se encuentra tanto en la web de Keras como en la de Tensorflow .
Además, aprovecharemos para redimensionar las imágenes y pasarlas a tamaño 224x224, que es el tamaño con el que se ha entrenado la red VGG16 que utilizaremos en un apartado posterior.
image_dataset_from_directory() para generar 3 conjuntos de datos (train_data, val_data y test_data) a partir de las carpetas analizadas. Las imágenes deben ser redimensionadas a tamaño 224x224 píxels RGB (224,224,3) y agrupadas en lotes de tamaño 32 (batch=32) manteniendo su rango dinámico.
directorio_entrenamiento = '/kaggle/input/landuse-scene-classification/images_train_test_val/train/'
directorio_validacion = '/kaggle/input/landuse-scene-classification/images_train_test_val/validation/'
directorio_prueba = '/kaggle/input/landuse-scene-classification/images_train_test_val/test/'
train_data = image_dataset_from_directory(
directorio_entrenamiento,
image_size=(224, 224),
batch_size=32,
shuffle=True,
seed=42,
interpolation='bilinear'
)
val_data = image_dataset_from_directory(
directorio_validacion,
image_size=(224, 224),
batch_size=32,
shuffle=True,
seed=42,
interpolation='bilinear'
)
test_data = image_dataset_from_directory(
directorio_prueba,
image_size=(224, 224),
batch_size=32,
shuffle=True,
seed=42,
interpolation='bilinear'
)
Found 7350 files belonging to 21 classes. Found 2100 files belonging to 21 classes. Found 1050 files belonging to 21 classes.
En este apartado, vamos a entrenar y evaluar un modelo muy sencillo completamente conectado para establecer un resultado de referencia.
Dado que en una red neuronal artificial las entradas son unidimensionales, lo primero que tenemos que hacer es redimensionar los datos de entrada (las imágenes) para convertirlos en arrays de una dimensión.
Como trabajar con imágenes de tamaño 224x224 en una red completamente conectada implicaría entrenar un número de parámetros excesivamente elevado definiremos un modelo en el que se realizará previamente un redimensionado de las imágenes de entrada a un tamaño de 32x32 y un achatamiento (flattening) de los píxeles para así generar un vector unidimensional de tamaño 3072 (32x32x3).
Posteriormente entrenaremos un clasificador (una red completamente conectada) para llevar a cabo la clasificación de nuestros datos.
En este apartado utilizaremos las capas Resizing, Rescaling, Flatten, Dense y Dropout de keras.
Sequential()) con las siguientes especificaciones:
summary() para comprobar la estructura de la red creada, así como el numero de parámetros que se deben entrenar. Se recomienda hacerlo en todos los ejercicios.
# Definición de la red
modelo_ANN = Sequential()
# Capa para reducir dimensiones
modelo_ANN.add(Resizing(32, 32, interpolation='bilinear', input_shape=(224, 224, 3)))
# Capa de reescalado
modelo_ANN.add(Rescaling(1./255, offset=0.0))
# Capa de flatten
modelo_ANN.add(Flatten())
# Capa de activacion
modelo_ANN.add(Dense(1024, activation='relu'))
# Capa de dropout
modelo_ANN.add(Dropout(0.5))
# Capa de salida
modelo_ANN.add(Dense(21, activation='softmax'))
# Compilación de la red
modelo_ANN.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001),
loss=tf.keras.losses.SparseCategoricalCrossentropy(),
metrics=['accuracy'])
# Definir callbacks
early_stopping = tf.keras.callbacks.EarlyStopping(patience=10, monitor='val_loss', restore_best_weights=True)
checkpoint = tf.keras.callbacks.ModelCheckpoint('mejor_modelo.h5', monitor='val_loss', save_best_only=True)
# Entrenamiento de la red
start_time = time.time()
entrenamiento_ANN = modelo_ANN.fit(train_data,
epochs=100,
validation_data=val_data,
callbacks=[early_stopping, checkpoint])
end_time = time.time()
Epoch 1/100 230/230 [==============================] - 25s 101ms/step - loss: 3.1202 - accuracy: 0.0624 - val_loss: 2.9953 - val_accuracy: 0.1057 Epoch 2/100 230/230 [==============================] - 24s 100ms/step - loss: 3.0013 - accuracy: 0.0898 - val_loss: 2.9710 - val_accuracy: 0.1119 Epoch 3/100 230/230 [==============================] - 23s 99ms/step - loss: 2.9561 - accuracy: 0.1022 - val_loss: 2.9374 - val_accuracy: 0.1171 Epoch 4/100 230/230 [==============================] - 24s 101ms/step - loss: 2.9110 - accuracy: 0.1192 - val_loss: 2.9000 - val_accuracy: 0.1386 Epoch 5/100 230/230 [==============================] - 23s 99ms/step - loss: 2.8658 - accuracy: 0.1377 - val_loss: 2.8695 - val_accuracy: 0.1510 Epoch 6/100 230/230 [==============================] - 24s 101ms/step - loss: 2.8237 - accuracy: 0.1502 - val_loss: 2.8430 - val_accuracy: 0.1567 Epoch 7/100 230/230 [==============================] - 25s 105ms/step - loss: 2.7829 - accuracy: 0.1645 - val_loss: 2.8130 - val_accuracy: 0.1705 Epoch 8/100 230/230 [==============================] - 29s 124ms/step - loss: 2.7458 - accuracy: 0.1727 - val_loss: 2.8011 - val_accuracy: 0.1795 Epoch 9/100 230/230 [==============================] - 24s 102ms/step - loss: 2.7141 - accuracy: 0.1890 - val_loss: 2.7726 - val_accuracy: 0.1957 Epoch 10/100 230/230 [==============================] - 24s 101ms/step - loss: 2.6690 - accuracy: 0.2012 - val_loss: 2.7786 - val_accuracy: 0.1771 Epoch 11/100 230/230 [==============================] - 24s 101ms/step - loss: 2.6411 - accuracy: 0.2082 - val_loss: 2.7521 - val_accuracy: 0.1914 Epoch 12/100 230/230 [==============================] - 23s 98ms/step - loss: 2.6203 - accuracy: 0.2116 - val_loss: 2.7392 - val_accuracy: 0.1929 Epoch 13/100 230/230 [==============================] - 24s 102ms/step - loss: 2.5739 - accuracy: 0.2322 - val_loss: 2.7407 - val_accuracy: 0.1967 Epoch 14/100 230/230 [==============================] - 24s 101ms/step - loss: 2.5538 - accuracy: 0.2392 - val_loss: 2.7008 - val_accuracy: 0.2062 Epoch 15/100 230/230 [==============================] - 29s 123ms/step - loss: 2.5140 - accuracy: 0.2473 - val_loss: 2.6873 - val_accuracy: 0.1957 Epoch 16/100 230/230 [==============================] - 25s 104ms/step - loss: 2.4897 - accuracy: 0.2582 - val_loss: 2.6864 - val_accuracy: 0.2105 Epoch 17/100 230/230 [==============================] - 23s 98ms/step - loss: 2.4524 - accuracy: 0.2754 - val_loss: 2.7011 - val_accuracy: 0.1843 Epoch 18/100 230/230 [==============================] - 24s 103ms/step - loss: 2.4259 - accuracy: 0.2812 - val_loss: 2.6682 - val_accuracy: 0.2124 Epoch 19/100 230/230 [==============================] - 23s 98ms/step - loss: 2.4072 - accuracy: 0.2822 - val_loss: 2.6694 - val_accuracy: 0.2000 Epoch 20/100 230/230 [==============================] - 24s 103ms/step - loss: 2.3627 - accuracy: 0.3019 - val_loss: 2.6445 - val_accuracy: 0.2200 Epoch 21/100 230/230 [==============================] - 24s 103ms/step - loss: 2.3381 - accuracy: 0.3078 - val_loss: 2.6392 - val_accuracy: 0.2181 Epoch 22/100 230/230 [==============================] - 24s 102ms/step - loss: 2.3117 - accuracy: 0.3268 - val_loss: 2.6297 - val_accuracy: 0.2238 Epoch 23/100 230/230 [==============================] - 24s 102ms/step - loss: 2.2863 - accuracy: 0.3263 - val_loss: 2.6328 - val_accuracy: 0.2229 Epoch 24/100 230/230 [==============================] - 23s 99ms/step - loss: 2.2496 - accuracy: 0.3328 - val_loss: 2.6317 - val_accuracy: 0.2195 Epoch 25/100 230/230 [==============================] - 24s 102ms/step - loss: 2.2355 - accuracy: 0.3460 - val_loss: 2.6352 - val_accuracy: 0.2224 Epoch 26/100 230/230 [==============================] - 24s 103ms/step - loss: 2.2089 - accuracy: 0.3577 - val_loss: 2.6083 - val_accuracy: 0.2238 Epoch 27/100 230/230 [==============================] - 29s 123ms/step - loss: 2.1783 - accuracy: 0.3679 - val_loss: 2.6255 - val_accuracy: 0.2219 Epoch 28/100 230/230 [==============================] - 23s 97ms/step - loss: 2.1515 - accuracy: 0.3720 - val_loss: 2.6149 - val_accuracy: 0.2290 Epoch 29/100 230/230 [==============================] - 24s 101ms/step - loss: 2.1268 - accuracy: 0.3710 - val_loss: 2.6101 - val_accuracy: 0.2205 Epoch 30/100 230/230 [==============================] - 24s 102ms/step - loss: 2.0907 - accuracy: 0.3943 - val_loss: 2.6021 - val_accuracy: 0.2343 Epoch 31/100 230/230 [==============================] - 25s 105ms/step - loss: 2.0700 - accuracy: 0.4005 - val_loss: 2.6052 - val_accuracy: 0.2257 Epoch 32/100 230/230 [==============================] - 23s 99ms/step - loss: 2.0369 - accuracy: 0.4103 - val_loss: 2.6077 - val_accuracy: 0.2319 Epoch 33/100 230/230 [==============================] - 24s 100ms/step - loss: 2.0132 - accuracy: 0.4200 - val_loss: 2.5866 - val_accuracy: 0.2410 Epoch 34/100 230/230 [==============================] - 25s 104ms/step - loss: 1.9992 - accuracy: 0.4152 - val_loss: 2.5859 - val_accuracy: 0.2376 Epoch 35/100 230/230 [==============================] - 29s 123ms/step - loss: 1.9624 - accuracy: 0.4348 - val_loss: 2.5994 - val_accuracy: 0.2200 Epoch 36/100 230/230 [==============================] - 24s 101ms/step - loss: 1.9350 - accuracy: 0.4439 - val_loss: 2.6008 - val_accuracy: 0.2286 Epoch 37/100 230/230 [==============================] - 26s 111ms/step - loss: 1.9264 - accuracy: 0.4454 - val_loss: 2.5698 - val_accuracy: 0.2371 Epoch 38/100 230/230 [==============================] - 24s 103ms/step - loss: 1.8909 - accuracy: 0.4475 - val_loss: 2.5929 - val_accuracy: 0.2395 Epoch 39/100 230/230 [==============================] - 26s 112ms/step - loss: 1.8726 - accuracy: 0.4601 - val_loss: 2.5826 - val_accuracy: 0.2343 Epoch 40/100 230/230 [==============================] - 28s 118ms/step - loss: 1.8471 - accuracy: 0.4748 - val_loss: 2.5810 - val_accuracy: 0.2452 Epoch 41/100 230/230 [==============================] - 25s 105ms/step - loss: 1.8096 - accuracy: 0.4796 - val_loss: 2.5968 - val_accuracy: 0.2338 Epoch 42/100 230/230 [==============================] - 32s 137ms/step - loss: 1.7910 - accuracy: 0.4812 - val_loss: 2.5934 - val_accuracy: 0.2486 Epoch 43/100 230/230 [==============================] - 27s 113ms/step - loss: 1.7576 - accuracy: 0.5004 - val_loss: 2.5880 - val_accuracy: 0.2462 Epoch 44/100 230/230 [==============================] - 25s 105ms/step - loss: 1.7329 - accuracy: 0.5102 - val_loss: 2.5824 - val_accuracy: 0.2329 Epoch 45/100 230/230 [==============================] - 24s 104ms/step - loss: 1.7276 - accuracy: 0.4997 - val_loss: 2.5952 - val_accuracy: 0.2510 Epoch 46/100 230/230 [==============================] - 26s 109ms/step - loss: 1.6883 - accuracy: 0.5162 - val_loss: 2.5942 - val_accuracy: 0.2481 Epoch 47/100 230/230 [==============================] - 25s 108ms/step - loss: 1.6700 - accuracy: 0.5147 - val_loss: 2.5956 - val_accuracy: 0.2448
#Función para mostrar las gráficas de Accuracy y Perdida
def mostrar_graficas(modelo):
acc = modelo.history['accuracy']
val_acc = modelo.history['val_accuracy']
loss = modelo.history['loss']
val_loss = modelo.history['val_loss']
epochs_range = range(len(acc))
plt.figure(figsize=(16, 8))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Accuracy entrenamiento')
plt.plot(epochs_range, val_acc, label='Accuracy validación')
plt.legend(loc='lower right')
plt.title('Accuracy durante entrenamiento y validación')
plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Pérdida entrenamiento')
plt.plot(epochs_range, val_loss, label='Pérdida validación')
plt.legend(loc='upper right')
plt.title('Pérdida durante entrenamiento y validación')
plt.show()
# Plot del training loss i l'accuracy
mostrar_graficas(entrenamiento_ANN)
#Información del modelo
modelo_ANN.summary()
Model: "sequential_3"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
resizing_1 (Resizing) (None, 32, 32, 3) 0
rescaling_2 (Rescaling) (None, 32, 32, 3) 0
flatten_4 (Flatten) (None, 3072) 0
dense_13 (Dense) (None, 1024) 3146752
dropout_2 (Dropout) (None, 1024) 0
dense_14 (Dense) (None, 21) 21525
=================================================================
Total params: 3,168,277
Trainable params: 3,168,277
Non-trainable params: 0
_________________________________________________________________
# Estadísticas y resultados del modelo
test_loss, test_acc = modelo_ANN.evaluate(test_data)
print("\nTiempo de entrenamiento:", end_time - start_time)
print('Pérdida en el conjunto de test:', test_loss)
print('Precisión en el conjunto de test:', test_acc)
33/33 [==============================] - 5s 113ms/step - loss: 2.5913 - accuracy: 0.2429 Tiempo de entrenamiento: 1311.375783920288 Pérdida en el conjunto de test: 2.5913305282592773 Precisión en el conjunto de test: 0.24285714328289032
Dadas las bajas prestaciones del modelo anterior vamos a probar otro tipo de redes con el objetivo de obtener unos mejores resultados en la tarea de clasificación que debemos llevar a cabo.
Las redes convolucionales (CNN) son especialmente adecuadas para modelar datos donde hay patrones en 2 dimensiones, como es el caso de las imágenes.
En la tarea de clasificación, la estructura de una CNN se divide en dos grandes bloques:
En el apartado anterior, el bloque "extractor de características" era extremadamente simple, por no decir inexistente. En este apartado, vamos a hacer uso de capas convolucionales para poder aprender mejores abstracciones de las imágenes de entrada con el fin de mejorar su clasificación.
En este apartado utilizaremos las capas Conv2D, MaxPooling2D, GlobalAveragePooling2D, Dense y Dropout de keras.
Nota: Se recomienda, a partir de este punto realizar el entrenamiento en una máquina con GPU (puede activarse en plataformas como Google Colab o Kaggle) con el fin de reducir los tiempos de entrenamiento.
Model()), implementa una red con las siguientes características:
# Definición de la red
# Dimensiones de entrada de los datos
input_shape = (224, 224, 3)
# Capa de entrada
input_layer = Input(shape=input_shape)
# Capa de rescalado
rescale_layer = Rescaling(scale=1./255)(input_layer)
# Bloque extractor de características
## Capa 1
conv1_layer = Conv2D(filters=16, kernel_size=(5, 5), padding='same', activation='relu')(rescale_layer)
pool1_layer = MaxPooling2D(pool_size=(2, 2))(conv1_layer)
## Capa 2
conv2_layer = Conv2D(filters=32, kernel_size=(3, 3), padding='same', activation='relu')(pool1_layer)
pool2_layer = MaxPooling2D(pool_size=(2, 2))(conv2_layer)
## Capa 3
conv3_layer = Conv2D(filters=64, kernel_size=(3, 3), padding='same', activation='relu')(pool2_layer)
pool3_layer = MaxPooling2D(pool_size=(2, 2))(conv3_layer)
## Capa Global
global_pool_layer = GlobalAveragePooling2D()(pool3_layer)
# Clasificador final
dense1_layer = Dense(units=64, activation='relu')(global_pool_layer)
dropout_layer = Dropout(rate=0.5)(dense1_layer)
# Capa Salida
output_layer = Dense(units=21, activation='softmax')(dropout_layer)
# Crear modelo
modelo_CNN = Model(inputs=input_layer, outputs=output_layer)
# Compilación de la red
optimizer = Adam(learning_rate=0.001)
modelo_CNN.compile(optimizer=optimizer, loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# EarlyStopping y ModelCheckpoint
earlystop_callback = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
checkpoint_callback = tf.keras.callbacks.ModelCheckpoint(filepath='best_weights.h5', monitor='val_loss', save_best_only=True)
# Entrenamiento
start_time = time.time()
entrenamiento_CNN = modelo_CNN.fit(train_data,
epochs=100,
validation_data=val_data,
callbacks=[earlystop_callback, checkpoint_callback])
end_time = time.time()
Epoch 1/100 230/230 [==============================] - 30s 115ms/step - loss: 2.9846 - accuracy: 0.0718 - val_loss: 2.8500 - val_accuracy: 0.1043 Epoch 2/100 230/230 [==============================] - 27s 116ms/step - loss: 2.7975 - accuracy: 0.1139 - val_loss: 2.6644 - val_accuracy: 0.1814 Epoch 3/100 230/230 [==============================] - 27s 115ms/step - loss: 2.6134 - accuracy: 0.1776 - val_loss: 2.4507 - val_accuracy: 0.2386 Epoch 4/100 230/230 [==============================] - 28s 118ms/step - loss: 2.4740 - accuracy: 0.2193 - val_loss: 2.3554 - val_accuracy: 0.2586 Epoch 5/100 230/230 [==============================] - 25s 104ms/step - loss: 2.3524 - accuracy: 0.2527 - val_loss: 2.1594 - val_accuracy: 0.3571 Epoch 6/100 230/230 [==============================] - 25s 107ms/step - loss: 2.2815 - accuracy: 0.2834 - val_loss: 2.0599 - val_accuracy: 0.3629 Epoch 7/100 230/230 [==============================] - 26s 109ms/step - loss: 2.1528 - accuracy: 0.3159 - val_loss: 1.9498 - val_accuracy: 0.4043 Epoch 8/100 230/230 [==============================] - 25s 106ms/step - loss: 2.0830 - accuracy: 0.3328 - val_loss: 1.9358 - val_accuracy: 0.3914 Epoch 9/100 230/230 [==============================] - 24s 103ms/step - loss: 2.0370 - accuracy: 0.3509 - val_loss: 1.8618 - val_accuracy: 0.3986 Epoch 10/100 230/230 [==============================] - 25s 107ms/step - loss: 1.9953 - accuracy: 0.3525 - val_loss: 1.8303 - val_accuracy: 0.4081 Epoch 11/100 230/230 [==============================] - 25s 108ms/step - loss: 1.9467 - accuracy: 0.3722 - val_loss: 1.7878 - val_accuracy: 0.4381 Epoch 12/100 230/230 [==============================] - 25s 104ms/step - loss: 1.9048 - accuracy: 0.3808 - val_loss: 1.7146 - val_accuracy: 0.4543 Epoch 13/100 230/230 [==============================] - 25s 107ms/step - loss: 1.8654 - accuracy: 0.3913 - val_loss: 1.6537 - val_accuracy: 0.4795 Epoch 14/100 230/230 [==============================] - 25s 108ms/step - loss: 1.8262 - accuracy: 0.3989 - val_loss: 1.6266 - val_accuracy: 0.4757 Epoch 15/100 230/230 [==============================] - 25s 107ms/step - loss: 1.7999 - accuracy: 0.4113 - val_loss: 1.5969 - val_accuracy: 0.4881 Epoch 16/100 230/230 [==============================] - 26s 110ms/step - loss: 1.7637 - accuracy: 0.4210 - val_loss: 1.5722 - val_accuracy: 0.4862 Epoch 17/100 230/230 [==============================] - 25s 107ms/step - loss: 1.7487 - accuracy: 0.4186 - val_loss: 1.7481 - val_accuracy: 0.4195 Epoch 18/100 230/230 [==============================] - 26s 109ms/step - loss: 1.7385 - accuracy: 0.4291 - val_loss: 1.5673 - val_accuracy: 0.4919 Epoch 19/100 230/230 [==============================] - 26s 109ms/step - loss: 1.7088 - accuracy: 0.4341 - val_loss: 1.4899 - val_accuracy: 0.5195 Epoch 20/100 230/230 [==============================] - 25s 107ms/step - loss: 1.6643 - accuracy: 0.4473 - val_loss: 1.4702 - val_accuracy: 0.5386 Epoch 21/100 230/230 [==============================] - 25s 107ms/step - loss: 1.6488 - accuracy: 0.4512 - val_loss: 1.5057 - val_accuracy: 0.5167 Epoch 22/100 230/230 [==============================] - 25s 105ms/step - loss: 1.6212 - accuracy: 0.4571 - val_loss: 1.4281 - val_accuracy: 0.5490 Epoch 23/100 230/230 [==============================] - 25s 108ms/step - loss: 1.6120 - accuracy: 0.4641 - val_loss: 1.4075 - val_accuracy: 0.5471 Epoch 24/100 230/230 [==============================] - 25s 105ms/step - loss: 1.5665 - accuracy: 0.4767 - val_loss: 1.3818 - val_accuracy: 0.5495 Epoch 25/100 230/230 [==============================] - 25s 104ms/step - loss: 1.5695 - accuracy: 0.4710 - val_loss: 1.3602 - val_accuracy: 0.5681 Epoch 26/100 230/230 [==============================] - 26s 110ms/step - loss: 1.5601 - accuracy: 0.4777 - val_loss: 1.4266 - val_accuracy: 0.5324 Epoch 27/100 230/230 [==============================] - 25s 107ms/step - loss: 1.5519 - accuracy: 0.4714 - val_loss: 1.2849 - val_accuracy: 0.5952 Epoch 28/100 230/230 [==============================] - 25s 106ms/step - loss: 1.5077 - accuracy: 0.4932 - val_loss: 1.3118 - val_accuracy: 0.5762 Epoch 29/100 230/230 [==============================] - 25s 107ms/step - loss: 1.4835 - accuracy: 0.5094 - val_loss: 1.2831 - val_accuracy: 0.5833 Epoch 30/100 230/230 [==============================] - 25s 108ms/step - loss: 1.4896 - accuracy: 0.4980 - val_loss: 1.2901 - val_accuracy: 0.5824 Epoch 31/100 230/230 [==============================] - 25s 106ms/step - loss: 1.4477 - accuracy: 0.5156 - val_loss: 1.2256 - val_accuracy: 0.6024 Epoch 32/100 230/230 [==============================] - 25s 104ms/step - loss: 1.4491 - accuracy: 0.5106 - val_loss: 1.2897 - val_accuracy: 0.5948 Epoch 33/100 230/230 [==============================] - 25s 106ms/step - loss: 1.4445 - accuracy: 0.5186 - val_loss: 1.2264 - val_accuracy: 0.6038 Epoch 34/100 230/230 [==============================] - 25s 106ms/step - loss: 1.4016 - accuracy: 0.5290 - val_loss: 1.1746 - val_accuracy: 0.6190 Epoch 35/100 230/230 [==============================] - 26s 108ms/step - loss: 1.3748 - accuracy: 0.5358 - val_loss: 1.1604 - val_accuracy: 0.6281 Epoch 36/100 230/230 [==============================] - 27s 116ms/step - loss: 1.3562 - accuracy: 0.5373 - val_loss: 1.1750 - val_accuracy: 0.6152 Epoch 37/100 230/230 [==============================] - 26s 110ms/step - loss: 1.3367 - accuracy: 0.5442 - val_loss: 1.1580 - val_accuracy: 0.6262 Epoch 38/100 230/230 [==============================] - 26s 109ms/step - loss: 1.3171 - accuracy: 0.5555 - val_loss: 1.1301 - val_accuracy: 0.6429 Epoch 39/100 230/230 [==============================] - 28s 116ms/step - loss: 1.2987 - accuracy: 0.5551 - val_loss: 1.0858 - val_accuracy: 0.6562 Epoch 40/100 230/230 [==============================] - 25s 105ms/step - loss: 1.3048 - accuracy: 0.5626 - val_loss: 1.0864 - val_accuracy: 0.6543 Epoch 41/100 230/230 [==============================] - 27s 117ms/step - loss: 1.2856 - accuracy: 0.5675 - val_loss: 1.1506 - val_accuracy: 0.6190 Epoch 42/100 230/230 [==============================] - 28s 117ms/step - loss: 1.2627 - accuracy: 0.5728 - val_loss: 1.0392 - val_accuracy: 0.6767 Epoch 43/100 230/230 [==============================] - 28s 120ms/step - loss: 1.2673 - accuracy: 0.5703 - val_loss: 1.0399 - val_accuracy: 0.6633 Epoch 44/100 230/230 [==============================] - 32s 135ms/step - loss: 1.2424 - accuracy: 0.5721 - val_loss: 1.0341 - val_accuracy: 0.6786 Epoch 45/100 230/230 [==============================] - 28s 120ms/step - loss: 1.2378 - accuracy: 0.5777 - val_loss: 1.0298 - val_accuracy: 0.6662 Epoch 46/100 230/230 [==============================] - 27s 114ms/step - loss: 1.2308 - accuracy: 0.5835 - val_loss: 1.0570 - val_accuracy: 0.6633 Epoch 47/100 230/230 [==============================] - 27s 115ms/step - loss: 1.2111 - accuracy: 0.5902 - val_loss: 1.0891 - val_accuracy: 0.6624 Epoch 48/100 230/230 [==============================] - 27s 116ms/step - loss: 1.1983 - accuracy: 0.5864 - val_loss: 1.0575 - val_accuracy: 0.6629 Epoch 49/100 230/230 [==============================] - 28s 115ms/step - loss: 1.1932 - accuracy: 0.5940 - val_loss: 0.9922 - val_accuracy: 0.6867 Epoch 50/100 230/230 [==============================] - 28s 119ms/step - loss: 1.1751 - accuracy: 0.6020 - val_loss: 0.9936 - val_accuracy: 0.6824 Epoch 51/100 230/230 [==============================] - 28s 120ms/step - loss: 1.1546 - accuracy: 0.6007 - val_loss: 0.9989 - val_accuracy: 0.6762 Epoch 52/100 230/230 [==============================] - 29s 122ms/step - loss: 1.1762 - accuracy: 0.6030 - val_loss: 1.0207 - val_accuracy: 0.6862 Epoch 53/100 230/230 [==============================] - 28s 120ms/step - loss: 1.1575 - accuracy: 0.5999 - val_loss: 0.9606 - val_accuracy: 0.6881 Epoch 54/100 230/230 [==============================] - 28s 119ms/step - loss: 1.1274 - accuracy: 0.6139 - val_loss: 0.9547 - val_accuracy: 0.6876 Epoch 55/100 230/230 [==============================] - 29s 122ms/step - loss: 1.1521 - accuracy: 0.5990 - val_loss: 0.9357 - val_accuracy: 0.7090 Epoch 56/100 230/230 [==============================] - 25s 108ms/step - loss: 1.1189 - accuracy: 0.6204 - val_loss: 0.9849 - val_accuracy: 0.6890 Epoch 57/100 230/230 [==============================] - 25s 106ms/step - loss: 1.1059 - accuracy: 0.6150 - val_loss: 0.9126 - val_accuracy: 0.7100 Epoch 58/100 230/230 [==============================] - 26s 109ms/step - loss: 1.0754 - accuracy: 0.6246 - val_loss: 0.8979 - val_accuracy: 0.7124 Epoch 59/100 230/230 [==============================] - 25s 107ms/step - loss: 1.0847 - accuracy: 0.6272 - val_loss: 0.9432 - val_accuracy: 0.7005 Epoch 60/100 230/230 [==============================] - 25s 107ms/step - loss: 1.0891 - accuracy: 0.6286 - val_loss: 1.0063 - val_accuracy: 0.6776 Epoch 61/100 230/230 [==============================] - 25s 106ms/step - loss: 1.0715 - accuracy: 0.6284 - val_loss: 0.9179 - val_accuracy: 0.7062 Epoch 62/100 230/230 [==============================] - 25s 107ms/step - loss: 1.0856 - accuracy: 0.6273 - val_loss: 0.9611 - val_accuracy: 0.6976 Epoch 63/100 230/230 [==============================] - 31s 131ms/step - loss: 1.0537 - accuracy: 0.6377 - val_loss: 0.9231 - val_accuracy: 0.7200 Epoch 64/100 230/230 [==============================] - 30s 128ms/step - loss: 1.0502 - accuracy: 0.6321 - val_loss: 0.9461 - val_accuracy: 0.7095 Epoch 65/100 230/230 [==============================] - 24s 104ms/step - loss: 1.0596 - accuracy: 0.6388 - val_loss: 0.9513 - val_accuracy: 0.7067 Epoch 66/100 230/230 [==============================] - 26s 109ms/step - loss: 1.0459 - accuracy: 0.6448 - val_loss: 0.9216 - val_accuracy: 0.7148 Epoch 67/100 230/230 [==============================] - 26s 111ms/step - loss: 1.0218 - accuracy: 0.6464 - val_loss: 0.8613 - val_accuracy: 0.7371 Epoch 68/100 230/230 [==============================] - 25s 107ms/step - loss: 1.0203 - accuracy: 0.6469 - val_loss: 0.8488 - val_accuracy: 0.7295 Epoch 69/100 230/230 [==============================] - 25s 108ms/step - loss: 1.0048 - accuracy: 0.6522 - val_loss: 0.8697 - val_accuracy: 0.7338 Epoch 70/100 230/230 [==============================] - 25s 106ms/step - loss: 1.0246 - accuracy: 0.6484 - val_loss: 0.8886 - val_accuracy: 0.7210 Epoch 71/100 230/230 [==============================] - 25s 107ms/step - loss: 0.9903 - accuracy: 0.6595 - val_loss: 0.8418 - val_accuracy: 0.7414 Epoch 72/100 230/230 [==============================] - 26s 113ms/step - loss: 0.9887 - accuracy: 0.6645 - val_loss: 0.8353 - val_accuracy: 0.7381 Epoch 73/100 230/230 [==============================] - 28s 117ms/step - loss: 1.0041 - accuracy: 0.6536 - val_loss: 0.8782 - val_accuracy: 0.7229 Epoch 74/100 230/230 [==============================] - 25s 108ms/step - loss: 0.9749 - accuracy: 0.6652 - val_loss: 0.8395 - val_accuracy: 0.7376 Epoch 75/100 230/230 [==============================] - 27s 116ms/step - loss: 0.9618 - accuracy: 0.6686 - val_loss: 0.8133 - val_accuracy: 0.7481 Epoch 76/100 230/230 [==============================] - 25s 108ms/step - loss: 0.9828 - accuracy: 0.6569 - val_loss: 0.8271 - val_accuracy: 0.7452 Epoch 77/100 230/230 [==============================] - 25s 108ms/step - loss: 0.9718 - accuracy: 0.6683 - val_loss: 0.8498 - val_accuracy: 0.7452 Epoch 78/100 230/230 [==============================] - 25s 107ms/step - loss: 0.9499 - accuracy: 0.6702 - val_loss: 0.8228 - val_accuracy: 0.7376 Epoch 79/100 230/230 [==============================] - 25s 108ms/step - loss: 0.9585 - accuracy: 0.6713 - val_loss: 0.8034 - val_accuracy: 0.7533 Epoch 80/100 230/230 [==============================] - 25s 107ms/step - loss: 0.9492 - accuracy: 0.6724 - val_loss: 0.8763 - val_accuracy: 0.7395 Epoch 81/100 230/230 [==============================] - 30s 129ms/step - loss: 0.9240 - accuracy: 0.6805 - val_loss: 0.7861 - val_accuracy: 0.7686 Epoch 82/100 230/230 [==============================] - 26s 111ms/step - loss: 0.9387 - accuracy: 0.6735 - val_loss: 0.8965 - val_accuracy: 0.7205 Epoch 83/100 230/230 [==============================] - 26s 110ms/step - loss: 0.9320 - accuracy: 0.6810 - val_loss: 0.7969 - val_accuracy: 0.7524 Epoch 84/100 230/230 [==============================] - 24s 104ms/step - loss: 0.9111 - accuracy: 0.6884 - val_loss: 0.8365 - val_accuracy: 0.7490 Epoch 85/100 230/230 [==============================] - 25s 106ms/step - loss: 0.9044 - accuracy: 0.6819 - val_loss: 0.8095 - val_accuracy: 0.7567 Epoch 86/100 230/230 [==============================] - 31s 130ms/step - loss: 0.8838 - accuracy: 0.6899 - val_loss: 0.8298 - val_accuracy: 0.7471 Epoch 87/100 230/230 [==============================] - 25s 107ms/step - loss: 0.9066 - accuracy: 0.6879 - val_loss: 0.7851 - val_accuracy: 0.7586 Epoch 88/100 230/230 [==============================] - 26s 109ms/step - loss: 0.8870 - accuracy: 0.6947 - val_loss: 0.8091 - val_accuracy: 0.7533 Epoch 89/100 230/230 [==============================] - 25s 107ms/step - loss: 0.9094 - accuracy: 0.6891 - val_loss: 0.7693 - val_accuracy: 0.7614 Epoch 90/100 230/230 [==============================] - 26s 109ms/step - loss: 0.8691 - accuracy: 0.6993 - val_loss: 0.7620 - val_accuracy: 0.7676 Epoch 91/100 230/230 [==============================] - 25s 107ms/step - loss: 0.8818 - accuracy: 0.6895 - val_loss: 0.7321 - val_accuracy: 0.7790 Epoch 92/100 230/230 [==============================] - 25s 106ms/step - loss: 0.8804 - accuracy: 0.6971 - val_loss: 0.7854 - val_accuracy: 0.7538 Epoch 93/100 230/230 [==============================] - 25s 107ms/step - loss: 0.8760 - accuracy: 0.6914 - val_loss: 0.7808 - val_accuracy: 0.7652 Epoch 94/100 230/230 [==============================] - 26s 109ms/step - loss: 0.8773 - accuracy: 0.6978 - val_loss: 0.7723 - val_accuracy: 0.7681 Epoch 95/100 230/230 [==============================] - 30s 127ms/step - loss: 0.8439 - accuracy: 0.7071 - val_loss: 0.7191 - val_accuracy: 0.7805 Epoch 96/100 230/230 [==============================] - 25s 105ms/step - loss: 0.8549 - accuracy: 0.7001 - val_loss: 0.7836 - val_accuracy: 0.7590 Epoch 97/100 230/230 [==============================] - 25s 106ms/step - loss: 0.8462 - accuracy: 0.7068 - val_loss: 0.7303 - val_accuracy: 0.7700 Epoch 98/100 230/230 [==============================] - 26s 108ms/step - loss: 0.8311 - accuracy: 0.7078 - val_loss: 0.7301 - val_accuracy: 0.7752 Epoch 99/100 230/230 [==============================] - 26s 111ms/step - loss: 0.8355 - accuracy: 0.7170 - val_loss: 0.6911 - val_accuracy: 0.7862 Epoch 100/100 230/230 [==============================] - 28s 117ms/step - loss: 0.8611 - accuracy: 0.7065 - val_loss: 0.7383 - val_accuracy: 0.7662
# Plot del training loss i l'accuracy
mostrar_graficas(entrenamiento_CNN)
#Información del modelo
modelo_CNN.summary()
Model: "model_2"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_5 (InputLayer) [(None, 224, 224, 3)] 0
rescaling_3 (Rescaling) (None, 224, 224, 3) 0
conv2d_6 (Conv2D) (None, 224, 224, 16) 1216
max_pooling2d_3 (MaxPooling (None, 112, 112, 16) 0
2D)
conv2d_7 (Conv2D) (None, 112, 112, 32) 4640
max_pooling2d_4 (MaxPooling (None, 56, 56, 32) 0
2D)
conv2d_8 (Conv2D) (None, 56, 56, 64) 18496
max_pooling2d_5 (MaxPooling (None, 28, 28, 64) 0
2D)
global_average_pooling2d_1 (None, 64) 0
(GlobalAveragePooling2D)
dense_15 (Dense) (None, 64) 4160
dropout_3 (Dropout) (None, 64) 0
dense_16 (Dense) (None, 21) 1365
=================================================================
Total params: 29,877
Trainable params: 29,877
Non-trainable params: 0
_________________________________________________________________
# Estadísticas y resultados del modelo
test_loss, test_acc = modelo_CNN.evaluate(test_data)
print("\nTiempo de entrenamiento:", end_time - start_time)
print('Pérdida en el conjunto de test:', test_loss)
print('Precisión en el conjunto de test:', test_acc)
33/33 [==============================] - 3s 66ms/step - loss: 0.7314 - accuracy: 0.7562 Tiempo de entrenamiento: 2858.381495952606 Pérdida en el conjunto de test: 0.7313904762268066 Precisión en el conjunto de test: 0.7561904788017273
En el apartado anterior hemos podido observar que, utilizando el tipo de redes adecuado, podemos obtener mejores resultados entrenando un número de parámetros muy inferior. Esto es debido a que las CNN consiguen extraer las características principales de los datos proporcionados (imágenes en nuestro caso).
En este apartado vamos a observar esta capacidad desde otro punto de vista: el de codificar y decodificar una imagen.
Para ello diseñaremos un autoencoder que sea capaz de reducir el tamaño de los datos de entrada pero captando las características principales de las imágenes para poder llevar a cabo una buena reconstrucción de las mismas.
Empezaremos rescalando externamente los datos que vamos a utilizar, para que estén en el rango (0,1), en lugar de realizarlo dentro de la red como hemos hecho en el apartado anterior:
# data rescalling
normalization_layer = Rescaling(1./255)
normalized_train_data = train_data.map(lambda x, y: (normalization_layer(x), y))
normalized_val_data = val_data.map(lambda x, y: (normalization_layer(x), y))
Además, en un autoencoder, en lugar de utilizar las etiquetas como objetivo (que es lo que se utiliza en un problema de clasificación), deben ser las propias imágenes las que se utilicen como objetivo de la red. Por tanto, crearemos una nueva base de datos de entrenamiento y validación donde son las propias imágenes las que hagan de etiquetas:
train_data_auto = normalized_train_data.map(lambda x, y: (x, x))
val_data_auto = normalized_val_data.map(lambda x, y: (x, x))
Comprobamos la estructura de la nueva base de datos:
image_batch, label_batch = iter(train_data_auto).get_next()
print("Las dimensiones de un batch de imágenes es: {}".format(image_batch.shape))
print("Las dimensiones de un batch de etiquetas es: {}".format(label_batch.shape))
Las dimensiones de un batch de imágenes es: (32, 224, 224, 3) Las dimensiones de un batch de etiquetas es: (32, 224, 224, 3)
Y que los datos tienen el rango dinámico adecuado:
first_image = image_batch[0]
print("En la primera imagen los valores mínimo y máximo son {} y {}, respectivamente"
.format(np.min(first_image),np.max(first_image)))
En la primera imagen los valores mínimo y máximo son 0.04708659648895264 y 0.9444637298583984, respectivamente
Una vez ya tenemos los datos en el formato adecuado vamos a diseñar el autoencoder. Para ello utilizaremos el bloque extractor del apartado anterior como codificador y reflejaremos su estructura en el decodificador utilizando las capas Conv2DTranspose y UpSampling2D de keras.
Model()), implementa un autoencoder con las siguientes características:
# Definición de la red
# Entrada
input_image = layers.Input(shape=(224, 224, 3))
# Capas convolucionales del codificador
## Capa 1
conv_1 = Conv2D(16, (5, 5), padding='same', activation='relu')(input_image)
pool_1 = MaxPooling2D((2, 2), padding='same')(conv_1)
## Capa 2
conv_2 = Conv2D(32, (3, 3), padding='same', activation='relu')(pool_1)
pool_2 = MaxPooling2D((2, 2), padding='same')(conv_2)
## Capa 3
conv_3 = Conv2D(64, (3, 3), padding='same', activation='relu')(pool_2)
encoder_output = MaxPooling2D((2, 2), padding='same')(conv_3)
# Capas convolucionales del decodificador
## Capa 1
deconv_1 = Conv2DTranspose(64, (3, 3), padding='same', activation='relu')(encoder_output)
upsample_1 = UpSampling2D((2, 2))(deconv_1)
## Capa 2
deconv_2 = Conv2DTranspose(32, (3, 3), padding='same', activation='relu')(upsample_1)
upsample_2 = UpSampling2D((2, 2))(deconv_2)
## Capa 3
deconv_3 = Conv2DTranspose(16, (5, 5), padding='same', activation='relu')(upsample_2)
upsample_3 = UpSampling2D((2, 2))(deconv_3)
decoder_output = Conv2DTranspose(3, (3, 3), padding='same', activation='sigmoid')(upsample_3)
# Definir modelo completo
modelo_autoencoder = Model(input_image, decoder_output)
# Compilación de la red
optimizer = Adam(learning_rate=0.001)
modelo_autoencoder.compile(optimizer=optimizer, metrics=['accuracy'], loss='mean_squared_error')
# Definir EarlyStopping y ModelCheckpoint
early_stopping = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=10, mode='min')
checkpoint = tf.keras.callbacks.ModelCheckpoint('best_model.h5', monitor='val_loss', save_best_only=True, mode='min')
# Entrenamiento de la red
start_time = time.time()
entrenamiento_autoencoder = modelo_autoencoder.fit(train_data_auto,
epochs=100,
validation_data=val_data_auto,
callbacks=[early_stopping, checkpoint])
end_time = time.time()
Epoch 1/100 230/230 [==============================] - 31s 127ms/step - loss: 0.0151 - accuracy: 0.4605 - val_loss: 0.0067 - val_accuracy: 0.5416 Epoch 2/100 230/230 [==============================] - 31s 132ms/step - loss: 0.0061 - accuracy: 0.5985 - val_loss: 0.0051 - val_accuracy: 0.6712 Epoch 3/100 230/230 [==============================] - 35s 149ms/step - loss: 0.0049 - accuracy: 0.6816 - val_loss: 0.0048 - val_accuracy: 0.6914 Epoch 4/100 230/230 [==============================] - 30s 127ms/step - loss: 0.0044 - accuracy: 0.6949 - val_loss: 0.0040 - val_accuracy: 0.6817 Epoch 5/100 230/230 [==============================] - 30s 126ms/step - loss: 0.0040 - accuracy: 0.7024 - val_loss: 0.0039 - val_accuracy: 0.7079 Epoch 6/100 230/230 [==============================] - 28s 119ms/step - loss: 0.0038 - accuracy: 0.7041 - val_loss: 0.0035 - val_accuracy: 0.7005 Epoch 7/100 230/230 [==============================] - 29s 122ms/step - loss: 0.0037 - accuracy: 0.7035 - val_loss: 0.0033 - val_accuracy: 0.7105 Epoch 8/100 230/230 [==============================] - 28s 121ms/step - loss: 0.0035 - accuracy: 0.7031 - val_loss: 0.0033 - val_accuracy: 0.6476 Epoch 9/100 230/230 [==============================] - 28s 121ms/step - loss: 0.0033 - accuracy: 0.7053 - val_loss: 0.0031 - val_accuracy: 0.7140 Epoch 10/100 230/230 [==============================] - 33s 141ms/step - loss: 0.0033 - accuracy: 0.7002 - val_loss: 0.0032 - val_accuracy: 0.7096 Epoch 11/100 230/230 [==============================] - 29s 124ms/step - loss: 0.0031 - accuracy: 0.7056 - val_loss: 0.0029 - val_accuracy: 0.6986 Epoch 12/100 230/230 [==============================] - 31s 131ms/step - loss: 0.0030 - accuracy: 0.7055 - val_loss: 0.0028 - val_accuracy: 0.7129 Epoch 13/100 230/230 [==============================] - 30s 128ms/step - loss: 0.0029 - accuracy: 0.7095 - val_loss: 0.0031 - val_accuracy: 0.6980 Epoch 14/100 230/230 [==============================] - 35s 148ms/step - loss: 0.0029 - accuracy: 0.7063 - val_loss: 0.0026 - val_accuracy: 0.7032 Epoch 15/100 230/230 [==============================] - 29s 123ms/step - loss: 0.0028 - accuracy: 0.7063 - val_loss: 0.0027 - val_accuracy: 0.7207 Epoch 16/100 230/230 [==============================] - 29s 123ms/step - loss: 0.0028 - accuracy: 0.7055 - val_loss: 0.0025 - val_accuracy: 0.7172 Epoch 17/100 230/230 [==============================] - 33s 141ms/step - loss: 0.0027 - accuracy: 0.7145 - val_loss: 0.0025 - val_accuracy: 0.7204 Epoch 18/100 230/230 [==============================] - 29s 122ms/step - loss: 0.0027 - accuracy: 0.7097 - val_loss: 0.0025 - val_accuracy: 0.7206 Epoch 19/100 230/230 [==============================] - 33s 141ms/step - loss: 0.0026 - accuracy: 0.7143 - val_loss: 0.0024 - val_accuracy: 0.7059 Epoch 20/100 230/230 [==============================] - 34s 145ms/step - loss: 0.0025 - accuracy: 0.7114 - val_loss: 0.0023 - val_accuracy: 0.7128 Epoch 21/100 230/230 [==============================] - 30s 127ms/step - loss: 0.0025 - accuracy: 0.7128 - val_loss: 0.0023 - val_accuracy: 0.7238 Epoch 22/100 230/230 [==============================] - 30s 127ms/step - loss: 0.0025 - accuracy: 0.7148 - val_loss: 0.0023 - val_accuracy: 0.7178 Epoch 23/100 230/230 [==============================] - 28s 121ms/step - loss: 0.0024 - accuracy: 0.7120 - val_loss: 0.0023 - val_accuracy: 0.7257 Epoch 24/100 230/230 [==============================] - 29s 124ms/step - loss: 0.0024 - accuracy: 0.7171 - val_loss: 0.0022 - val_accuracy: 0.7319 Epoch 25/100 230/230 [==============================] - 33s 139ms/step - loss: 0.0023 - accuracy: 0.7187 - val_loss: 0.0022 - val_accuracy: 0.7286 Epoch 26/100 230/230 [==============================] - 29s 125ms/step - loss: 0.0023 - accuracy: 0.7236 - val_loss: 0.0021 - val_accuracy: 0.7286 Epoch 27/100 230/230 [==============================] - 29s 123ms/step - loss: 0.0025 - accuracy: 0.7057 - val_loss: 0.0021 - val_accuracy: 0.7228 Epoch 28/100 230/230 [==============================] - 28s 119ms/step - loss: 0.0022 - accuracy: 0.7152 - val_loss: 0.0021 - val_accuracy: 0.7260 Epoch 29/100 230/230 [==============================] - 29s 122ms/step - loss: 0.0022 - accuracy: 0.7166 - val_loss: 0.0021 - val_accuracy: 0.7058 Epoch 30/100 230/230 [==============================] - 29s 124ms/step - loss: 0.0022 - accuracy: 0.7225 - val_loss: 0.0020 - val_accuracy: 0.7234 Epoch 31/100 230/230 [==============================] - 28s 120ms/step - loss: 0.0022 - accuracy: 0.7195 - val_loss: 0.0020 - val_accuracy: 0.7404 Epoch 32/100 230/230 [==============================] - 28s 121ms/step - loss: 0.0021 - accuracy: 0.7190 - val_loss: 0.0020 - val_accuracy: 0.7128 Epoch 33/100 230/230 [==============================] - 28s 121ms/step - loss: 0.0021 - accuracy: 0.7208 - val_loss: 0.0020 - val_accuracy: 0.7366 Epoch 34/100 230/230 [==============================] - 29s 125ms/step - loss: 0.0021 - accuracy: 0.7156 - val_loss: 0.0020 - val_accuracy: 0.7190 Epoch 35/100 230/230 [==============================] - 33s 140ms/step - loss: 0.0021 - accuracy: 0.7205 - val_loss: 0.0020 - val_accuracy: 0.7192 Epoch 36/100 230/230 [==============================] - 29s 122ms/step - loss: 0.0020 - accuracy: 0.7258 - val_loss: 0.0019 - val_accuracy: 0.7390 Epoch 37/100 230/230 [==============================] - 29s 123ms/step - loss: 0.0020 - accuracy: 0.7202 - val_loss: 0.0021 - val_accuracy: 0.6858 Epoch 38/100 230/230 [==============================] - 28s 121ms/step - loss: 0.0020 - accuracy: 0.7247 - val_loss: 0.0019 - val_accuracy: 0.7325 Epoch 39/100 230/230 [==============================] - 29s 123ms/step - loss: 0.0020 - accuracy: 0.7180 - val_loss: 0.0020 - val_accuracy: 0.7265 Epoch 40/100 230/230 [==============================] - 29s 122ms/step - loss: 0.0020 - accuracy: 0.7226 - val_loss: 0.0018 - val_accuracy: 0.7319 Epoch 41/100 230/230 [==============================] - 28s 121ms/step - loss: 0.0020 - accuracy: 0.7252 - val_loss: 0.0018 - val_accuracy: 0.7317 Epoch 42/100 230/230 [==============================] - 29s 122ms/step - loss: 0.0019 - accuracy: 0.7207 - val_loss: 0.0019 - val_accuracy: 0.7360 Epoch 43/100 230/230 [==============================] - 28s 121ms/step - loss: 0.0019 - accuracy: 0.7250 - val_loss: 0.0018 - val_accuracy: 0.7357 Epoch 44/100 230/230 [==============================] - 29s 122ms/step - loss: 0.0020 - accuracy: 0.7206 - val_loss: 0.0018 - val_accuracy: 0.7274 Epoch 45/100 230/230 [==============================] - 29s 122ms/step - loss: 0.0019 - accuracy: 0.7260 - val_loss: 0.0018 - val_accuracy: 0.7364 Epoch 46/100 230/230 [==============================] - 29s 122ms/step - loss: 0.0019 - accuracy: 0.7235 - val_loss: 0.0017 - val_accuracy: 0.7351 Epoch 47/100 230/230 [==============================] - 29s 123ms/step - loss: 0.0019 - accuracy: 0.7277 - val_loss: 0.0017 - val_accuracy: 0.7289 Epoch 48/100 230/230 [==============================] - 29s 123ms/step - loss: 0.0019 - accuracy: 0.7216 - val_loss: 0.0018 - val_accuracy: 0.7388 Epoch 49/100 230/230 [==============================] - 29s 123ms/step - loss: 0.0019 - accuracy: 0.7228 - val_loss: 0.0018 - val_accuracy: 0.7309 Epoch 50/100 230/230 [==============================] - 30s 126ms/step - loss: 0.0018 - accuracy: 0.7181 - val_loss: 0.0018 - val_accuracy: 0.7274 Epoch 51/100 230/230 [==============================] - 35s 151ms/step - loss: 0.0018 - accuracy: 0.7253 - val_loss: 0.0017 - val_accuracy: 0.7360 Epoch 52/100 230/230 [==============================] - 29s 125ms/step - loss: 0.0018 - accuracy: 0.7194 - val_loss: 0.0020 - val_accuracy: 0.7356 Epoch 53/100 230/230 [==============================] - 29s 125ms/step - loss: 0.0018 - accuracy: 0.7268 - val_loss: 0.0017 - val_accuracy: 0.7261 Epoch 54/100 230/230 [==============================] - 30s 127ms/step - loss: 0.0018 - accuracy: 0.7282 - val_loss: 0.0017 - val_accuracy: 0.7339 Epoch 55/100 230/230 [==============================] - 31s 132ms/step - loss: 0.0018 - accuracy: 0.7214 - val_loss: 0.0017 - val_accuracy: 0.7358 Epoch 56/100 230/230 [==============================] - 34s 143ms/step - loss: 0.0018 - accuracy: 0.7267 - val_loss: 0.0017 - val_accuracy: 0.7380 Epoch 57/100 230/230 [==============================] - 29s 123ms/step - loss: 0.0018 - accuracy: 0.7234 - val_loss: 0.0017 - val_accuracy: 0.6977 Epoch 58/100 230/230 [==============================] - 29s 126ms/step - loss: 0.0017 - accuracy: 0.7276 - val_loss: 0.0016 - val_accuracy: 0.7140 Epoch 59/100 230/230 [==============================] - 29s 122ms/step - loss: 0.0018 - accuracy: 0.7221 - val_loss: 0.0016 - val_accuracy: 0.7325 Epoch 60/100 230/230 [==============================] - 30s 127ms/step - loss: 0.0017 - accuracy: 0.7296 - val_loss: 0.0016 - val_accuracy: 0.7388 Epoch 61/100 230/230 [==============================] - 30s 127ms/step - loss: 0.0017 - accuracy: 0.7274 - val_loss: 0.0016 - val_accuracy: 0.7435 Epoch 62/100 230/230 [==============================] - 30s 126ms/step - loss: 0.0017 - accuracy: 0.7266 - val_loss: 0.0017 - val_accuracy: 0.7214 Epoch 63/100 230/230 [==============================] - 29s 126ms/step - loss: 0.0017 - accuracy: 0.7297 - val_loss: 0.0017 - val_accuracy: 0.7407 Epoch 64/100 230/230 [==============================] - 29s 123ms/step - loss: 0.0027 - accuracy: 0.6955 - val_loss: 0.0018 - val_accuracy: 0.7342 Epoch 65/100 230/230 [==============================] - 31s 133ms/step - loss: 0.0018 - accuracy: 0.7334 - val_loss: 0.0017 - val_accuracy: 0.7342 Epoch 66/100 230/230 [==============================] - 33s 137ms/step - loss: 0.0017 - accuracy: 0.7301 - val_loss: 0.0017 - val_accuracy: 0.7108 Epoch 67/100 230/230 [==============================] - 35s 150ms/step - loss: 0.0017 - accuracy: 0.7290 - val_loss: 0.0016 - val_accuracy: 0.7335 Epoch 68/100 230/230 [==============================] - 31s 131ms/step - loss: 0.0017 - accuracy: 0.7292 - val_loss: 0.0017 - val_accuracy: 0.6722 Epoch 69/100 230/230 [==============================] - 35s 151ms/step - loss: 0.0017 - accuracy: 0.7274 - val_loss: 0.0016 - val_accuracy: 0.7292 Epoch 70/100 230/230 [==============================] - 32s 137ms/step - loss: 0.0017 - accuracy: 0.7285 - val_loss: 0.0016 - val_accuracy: 0.7349 Epoch 71/100 230/230 [==============================] - 32s 134ms/step - loss: 0.0017 - accuracy: 0.7325 - val_loss: 0.0016 - val_accuracy: 0.7262 Epoch 72/100 230/230 [==============================] - 35s 149ms/step - loss: 0.0017 - accuracy: 0.7322 - val_loss: 0.0016 - val_accuracy: 0.7108 Epoch 73/100 230/230 [==============================] - 29s 120ms/step - loss: 0.0016 - accuracy: 0.7335 - val_loss: 0.0016 - val_accuracy: 0.7195 Epoch 74/100 230/230 [==============================] - 29s 122ms/step - loss: 0.0017 - accuracy: 0.7316 - val_loss: 0.0019 - val_accuracy: 0.7385 Epoch 75/100 230/230 [==============================] - 33s 143ms/step - loss: 0.0017 - accuracy: 0.7316 - val_loss: 0.0016 - val_accuracy: 0.7424 Epoch 76/100 230/230 [==============================] - 33s 141ms/step - loss: 0.0016 - accuracy: 0.7340 - val_loss: 0.0016 - val_accuracy: 0.7296 Epoch 77/100 230/230 [==============================] - 28s 120ms/step - loss: 0.0016 - accuracy: 0.7285 - val_loss: 0.0015 - val_accuracy: 0.7435 Epoch 78/100 230/230 [==============================] - 33s 138ms/step - loss: 0.0016 - accuracy: 0.7309 - val_loss: 0.0015 - val_accuracy: 0.7456 Epoch 79/100 230/230 [==============================] - 28s 121ms/step - loss: 0.0016 - accuracy: 0.7317 - val_loss: 0.0016 - val_accuracy: 0.7341 Epoch 80/100 230/230 [==============================] - 29s 122ms/step - loss: 0.0016 - accuracy: 0.7335 - val_loss: 0.0016 - val_accuracy: 0.7461 Epoch 81/100 230/230 [==============================] - 33s 141ms/step - loss: 0.0016 - accuracy: 0.7324 - val_loss: 0.0016 - val_accuracy: 0.7462 Epoch 82/100 230/230 [==============================] - 33s 142ms/step - loss: 0.0016 - accuracy: 0.7330 - val_loss: 0.0015 - val_accuracy: 0.7247 Epoch 83/100 230/230 [==============================] - 28s 121ms/step - loss: 0.0016 - accuracy: 0.7356 - val_loss: 0.0015 - val_accuracy: 0.7178 Epoch 84/100 230/230 [==============================] - 29s 123ms/step - loss: 0.0016 - accuracy: 0.7325 - val_loss: 0.0015 - val_accuracy: 0.7451 Epoch 85/100 230/230 [==============================] - 33s 141ms/step - loss: 0.0016 - accuracy: 0.7331 - val_loss: 0.0015 - val_accuracy: 0.7297 Epoch 86/100 230/230 [==============================] - 33s 140ms/step - loss: 0.0016 - accuracy: 0.7323 - val_loss: 0.0015 - val_accuracy: 0.7372 Epoch 87/100 230/230 [==============================] - 28s 120ms/step - loss: 0.0016 - accuracy: 0.7315 - val_loss: 0.0015 - val_accuracy: 0.7310 Epoch 88/100 230/230 [==============================] - 34s 144ms/step - loss: 0.0015 - accuracy: 0.7356 - val_loss: 0.0015 - val_accuracy: 0.7453 Epoch 89/100 230/230 [==============================] - 29s 122ms/step - loss: 0.0015 - accuracy: 0.7350 - val_loss: 0.0015 - val_accuracy: 0.7411 Epoch 90/100 230/230 [==============================] - 28s 118ms/step - loss: 0.0016 - accuracy: 0.7339 - val_loss: 0.0016 - val_accuracy: 0.7138 Epoch 91/100 230/230 [==============================] - 29s 122ms/step - loss: 0.0015 - accuracy: 0.7339 - val_loss: 0.0015 - val_accuracy: 0.7438 Epoch 92/100 230/230 [==============================] - 28s 120ms/step - loss: 0.0015 - accuracy: 0.7313 - val_loss: 0.0014 - val_accuracy: 0.7411 Epoch 93/100 230/230 [==============================] - 32s 138ms/step - loss: 0.0015 - accuracy: 0.7343 - val_loss: 0.0015 - val_accuracy: 0.7131 Epoch 94/100 230/230 [==============================] - 28s 121ms/step - loss: 0.0016 - accuracy: 0.7287 - val_loss: 0.0017 - val_accuracy: 0.7380 Epoch 95/100 230/230 [==============================] - 29s 123ms/step - loss: 0.0015 - accuracy: 0.7335 - val_loss: 0.0016 - val_accuracy: 0.6804 Epoch 96/100 230/230 [==============================] - 28s 118ms/step - loss: 0.0015 - accuracy: 0.7403 - val_loss: 0.0015 - val_accuracy: 0.7195 Epoch 97/100 230/230 [==============================] - 28s 118ms/step - loss: 0.0015 - accuracy: 0.7346 - val_loss: 0.0015 - val_accuracy: 0.7230 Epoch 98/100 230/230 [==============================] - 32s 136ms/step - loss: 0.0015 - accuracy: 0.7350 - val_loss: 0.0015 - val_accuracy: 0.7528 Epoch 99/100 230/230 [==============================] - 28s 120ms/step - loss: 0.0015 - accuracy: 0.7355 - val_loss: 0.0014 - val_accuracy: 0.7440 Epoch 100/100 230/230 [==============================] - 28s 121ms/step - loss: 0.0015 - accuracy: 0.7360 - val_loss: 0.0014 - val_accuracy: 0.7495
# Representación del loss
mostrar_graficas(entrenamiento_autoencoder)
La evaluación del modelo obtenido puede hacerse en este caso tanto de forma cuantitativa (calculando el MSE entre las imágenes originales y reconstruídas del conjunto de test) como cualitativa (mostrando imágenes originales y reconstruídas).
normalization_layer tal y como se ha hecho con los conjuntos de entrenamiento y test al inicio de este bloque.test_data_auto en el que las imágenes sean también el objetivo y substituyan a las etiquetas. # Normalización de los datos
normalization_layer = Rescaling(1./255)
normalized_test_data = test_data.map(lambda x, y: (normalization_layer(x), y))
test_data_auto = normalized_test_data.map(lambda x, y: (x, x))
image_batch, label_batch = iter(test_data_auto).get_next()
print("Las dimensiones de un batch de imágenes es: {}".format(image_batch.shape))
print("Las dimensiones de un batch de etiquetas es: {}".format(label_batch.shape))
first_image = image_batch[0]
print("En la primera imagen los valores mínimo y máximo son {} y {}, respectivamente"
.format(np.min(first_image),np.max(first_image)))
Las dimensiones de un batch de imágenes es: (32, 224, 224, 3) Las dimensiones de un batch de etiquetas es: (32, 224, 224, 3) En la primera imagen los valores mínimo y máximo son 0.6426967978477478 y 0.9833736419677734, respectivamente
# Evaluación del modelo
test_loss, test_acc = modelo_autoencoder.evaluate(test_data_auto)
print("\nTiempo de entrenamiento:", end_time - start_time)
print('Pérdida en el conjunto de test:', test_loss)
print('Precisión en el conjunto de test:', test_acc)
33/33 [==============================] - 3s 79ms/step - loss: 0.0014 - accuracy: 0.7513 Tiempo de entrenamiento: 3535.9279289245605 Pérdida en el conjunto de test: 0.0014285397483035922 Precisión en el conjunto de test: 0.7512709498405457
# Visualización de los datos
n = 4 # número de parejas de imágenes a mostrar
plt.figure(figsize=(15, 6*n))
for i, (image, label) in enumerate(test_data_auto.take(n)):
# imagen original
ax = plt.subplot(n, 2, 2*i+1)
plt.imshow(np.array(image[0]* 255, dtype=int))
plt.title('Original')
plt.axis('off')
# imagen reconstruida
ax = plt.subplot(n, 2, 2*i+2)
reconstructed = modelo_autoencoder.predict(image)[0]
plt.imshow(np.array(reconstructed* 255, dtype=int))
plt.title('Reconstruida')
plt.axis('off')
plt.show()
1/1 [==============================] - 0s 306ms/step 1/1 [==============================] - 0s 49ms/step 1/1 [==============================] - 0s 38ms/step 1/1 [==============================] - 0s 29ms/step
Las redes neuronales convolucionales profundas nos brindan la posibilidad de mejorar la capacidad de aprendizaje de un modelo. Algunas arquitecturas comunes, pueden incluir cientos de capas convolucionales. No obstante, entrenar estas arquitecturas desde cero puede resultar costoso tanto en términos de tiempo como de recursos, además de requerir conjuntos de datos bastante grandes.
En este apartado, aplicaremos transfer learning con el fin de ahorrarnos parte de dicho entrenamiento. Esta metodología consiste en aprovechar los pesos de un modelo entrenado en otra base de datos y para otra tarea. En concreto, utilizaremos el modelo VGG16 preentrenado en Imagenet, y lo adaptaremos para clasificar las 21 categorías de nuestra base de datos. En la versión de VGG16 de keras existe la opción de cargar los pesos entrenados en Imagenet sin las 3 capas totalmente conectadas de la parte final de la red (opción include_top = False), nosotros substituiremos esas 3 capas y reentrenaremos el conjunto con el resto de pesos congelados.
Para reutilizar el modelo correctamente es necesario preprocesar los datos tal y como se hizo durante el entrenamiento en la base de datos original. Keras nos facilita aplicar la normalización en el caso de modelos preentrenados; para el caso de VGG16 revisar la documentación de prepocess_input (tened en cuenta que la función se aplica sobre imágenes con rango dinámico de 0 a 255).
from tensorflow.keras.applications.vgg16 import VGG16
from tensorflow.keras.applications.vgg16 import preprocess_input
from tensorflow.keras.preprocessing.image import ImageDataGenerator
## Loading VGG16 model
vgg = VGG16(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
for layer in vgg.layers:
layer.trainable = False
Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/vgg16/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5 58889256/58889256 [==============================] - 4s 0us/step
# Definición de la red
# Substituir últimas capas completamente conectadas
flatten = Flatten()(vgg.output)
fc1 = Dense(50, activation='relu')(flatten)
fc2 = Dense(20, activation='relu')(fc1)
output = Dense(21, activation='softmax')(fc2)
# Crear modelo
modelo_VGG = Model(inputs=vgg.input, outputs=output)
# Compilación de la red
opt = Adam(learning_rate=0.0001)
modelo_VGG.compile(optimizer=opt, loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# Definir EarlyStopping y ModelCheckpoint
early_stop = tf.keras.callbacks.EarlyStopping(monitor='val_accuracy', patience=10, verbose=1)
best_model = tf.keras.callbacks.ModelCheckpoint('best_model.h5', monitor='val_accuracy', save_best_only=True, verbose=1)
# Entrenamiento de la red
start_time = time.time()
entrenamiento_VGG = modelo_VGG.fit(train_data, epochs=100, validation_data=val_data, callbacks=[early_stop, best_model])
end_time = time.time()
Epoch 1/100 230/230 [==============================] - ETA: 0s - loss: 2.6452 - accuracy: 0.3216 Epoch 1: val_accuracy improved from -inf to 0.55667, saving model to best_model.h5 230/230 [==============================] - 35s 134ms/step - loss: 2.6452 - accuracy: 0.3216 - val_loss: 1.5963 - val_accuracy: 0.5567 Epoch 2/100 230/230 [==============================] - ETA: 0s - loss: 0.8850 - accuracy: 0.7320 Epoch 2: val_accuracy improved from 0.55667 to 0.70857, saving model to best_model.h5 230/230 [==============================] - 28s 118ms/step - loss: 0.8850 - accuracy: 0.7320 - val_loss: 1.0719 - val_accuracy: 0.7086 Epoch 3/100 230/230 [==============================] - ETA: 0s - loss: 0.3207 - accuracy: 0.9093 Epoch 3: val_accuracy improved from 0.70857 to 0.75857, saving model to best_model.h5 230/230 [==============================] - 27s 115ms/step - loss: 0.3207 - accuracy: 0.9093 - val_loss: 0.9419 - val_accuracy: 0.7586 Epoch 4/100 230/230 [==============================] - ETA: 0s - loss: 0.1353 - accuracy: 0.9695 Epoch 4: val_accuracy improved from 0.75857 to 0.78000, saving model to best_model.h5 230/230 [==============================] - 27s 115ms/step - loss: 0.1353 - accuracy: 0.9695 - val_loss: 0.9114 - val_accuracy: 0.7800 Epoch 5/100 230/230 [==============================] - ETA: 0s - loss: 0.0622 - accuracy: 0.9880 Epoch 5: val_accuracy improved from 0.78000 to 0.78381, saving model to best_model.h5 230/230 [==============================] - 26s 112ms/step - loss: 0.0622 - accuracy: 0.9880 - val_loss: 0.9547 - val_accuracy: 0.7838 Epoch 6/100 230/230 [==============================] - ETA: 0s - loss: 0.0325 - accuracy: 0.9956 Epoch 6: val_accuracy improved from 0.78381 to 0.79905, saving model to best_model.h5 230/230 [==============================] - 27s 117ms/step - loss: 0.0325 - accuracy: 0.9956 - val_loss: 0.9345 - val_accuracy: 0.7990 Epoch 7/100 230/230 [==============================] - ETA: 0s - loss: 0.0200 - accuracy: 0.9967 Epoch 7: val_accuracy did not improve from 0.79905 230/230 [==============================] - 28s 119ms/step - loss: 0.0200 - accuracy: 0.9967 - val_loss: 0.9353 - val_accuracy: 0.7967 Epoch 8/100 230/230 [==============================] - ETA: 0s - loss: 0.0103 - accuracy: 0.9989 Epoch 8: val_accuracy improved from 0.79905 to 0.80238, saving model to best_model.h5 230/230 [==============================] - 27s 113ms/step - loss: 0.0103 - accuracy: 0.9989 - val_loss: 0.9400 - val_accuracy: 0.8024 Epoch 9/100 230/230 [==============================] - ETA: 0s - loss: 0.0065 - accuracy: 0.9995 Epoch 9: val_accuracy improved from 0.80238 to 0.80476, saving model to best_model.h5 230/230 [==============================] - 27s 115ms/step - loss: 0.0065 - accuracy: 0.9995 - val_loss: 0.9531 - val_accuracy: 0.8048 Epoch 10/100 230/230 [==============================] - ETA: 0s - loss: 0.0044 - accuracy: 0.9997 Epoch 10: val_accuracy improved from 0.80476 to 0.80857, saving model to best_model.h5 230/230 [==============================] - 28s 119ms/step - loss: 0.0044 - accuracy: 0.9997 - val_loss: 0.9569 - val_accuracy: 0.8086 Epoch 11/100 230/230 [==============================] - ETA: 0s - loss: 0.0030 - accuracy: 1.0000 Epoch 11: val_accuracy did not improve from 0.80857 230/230 [==============================] - 27s 114ms/step - loss: 0.0030 - accuracy: 1.0000 - val_loss: 0.9617 - val_accuracy: 0.8086 Epoch 12/100 230/230 [==============================] - ETA: 0s - loss: 0.0023 - accuracy: 1.0000 Epoch 12: val_accuracy improved from 0.80857 to 0.80952, saving model to best_model.h5 230/230 [==============================] - 27s 116ms/step - loss: 0.0023 - accuracy: 1.0000 - val_loss: 0.9659 - val_accuracy: 0.8095 Epoch 13/100 230/230 [==============================] - ETA: 0s - loss: 0.0018 - accuracy: 1.0000 Epoch 13: val_accuracy did not improve from 0.80952 230/230 [==============================] - 27s 114ms/step - loss: 0.0018 - accuracy: 1.0000 - val_loss: 0.9701 - val_accuracy: 0.8086 Epoch 14/100 230/230 [==============================] - ETA: 0s - loss: 0.0015 - accuracy: 1.0000 Epoch 14: val_accuracy improved from 0.80952 to 0.81000, saving model to best_model.h5 230/230 [==============================] - 28s 118ms/step - loss: 0.0015 - accuracy: 1.0000 - val_loss: 0.9728 - val_accuracy: 0.8100 Epoch 15/100 230/230 [==============================] - ETA: 0s - loss: 0.0012 - accuracy: 1.0000 Epoch 15: val_accuracy improved from 0.81000 to 0.81048, saving model to best_model.h5 230/230 [==============================] - 28s 121ms/step - loss: 0.0012 - accuracy: 1.0000 - val_loss: 0.9781 - val_accuracy: 0.8105 Epoch 16/100 230/230 [==============================] - ETA: 0s - loss: 0.0010 - accuracy: 1.0000 Epoch 16: val_accuracy did not improve from 0.81048 230/230 [==============================] - 28s 121ms/step - loss: 0.0010 - accuracy: 1.0000 - val_loss: 0.9814 - val_accuracy: 0.8105 Epoch 17/100 230/230 [==============================] - ETA: 0s - loss: 8.7704e-04 - accuracy: 1.0000 Epoch 17: val_accuracy improved from 0.81048 to 0.81238, saving model to best_model.h5 230/230 [==============================] - 28s 119ms/step - loss: 8.7704e-04 - accuracy: 1.0000 - val_loss: 0.9856 - val_accuracy: 0.8124 Epoch 18/100 230/230 [==============================] - ETA: 0s - loss: 7.3961e-04 - accuracy: 1.0000 Epoch 18: val_accuracy improved from 0.81238 to 0.81381, saving model to best_model.h5 230/230 [==============================] - 28s 116ms/step - loss: 7.3961e-04 - accuracy: 1.0000 - val_loss: 0.9924 - val_accuracy: 0.8138 Epoch 19/100 230/230 [==============================] - ETA: 0s - loss: 6.3542e-04 - accuracy: 1.0000 Epoch 19: val_accuracy did not improve from 0.81381 230/230 [==============================] - 28s 118ms/step - loss: 6.3542e-04 - accuracy: 1.0000 - val_loss: 0.9976 - val_accuracy: 0.8138 Epoch 20/100 230/230 [==============================] - ETA: 0s - loss: 5.3522e-04 - accuracy: 1.0000 Epoch 20: val_accuracy improved from 0.81381 to 0.81571, saving model to best_model.h5 230/230 [==============================] - 27s 113ms/step - loss: 5.3522e-04 - accuracy: 1.0000 - val_loss: 1.0025 - val_accuracy: 0.8157 Epoch 21/100 230/230 [==============================] - ETA: 0s - loss: 4.9257e-04 - accuracy: 1.0000 Epoch 21: val_accuracy did not improve from 0.81571 230/230 [==============================] - 27s 114ms/step - loss: 4.9257e-04 - accuracy: 1.0000 - val_loss: 1.0275 - val_accuracy: 0.8133 Epoch 22/100 230/230 [==============================] - ETA: 0s - loss: 8.0284e-04 - accuracy: 0.9999 Epoch 22: val_accuracy did not improve from 0.81571 230/230 [==============================] - 31s 131ms/step - loss: 8.0284e-04 - accuracy: 0.9999 - val_loss: 1.0382 - val_accuracy: 0.8148 Epoch 23/100 230/230 [==============================] - ETA: 0s - loss: 5.7824e-04 - accuracy: 1.0000 Epoch 23: val_accuracy improved from 0.81571 to 0.81762, saving model to best_model.h5 230/230 [==============================] - 28s 119ms/step - loss: 5.7824e-04 - accuracy: 1.0000 - val_loss: 1.0006 - val_accuracy: 0.8176 Epoch 24/100 230/230 [==============================] - ETA: 0s - loss: 0.1472 - accuracy: 0.9566 Epoch 24: val_accuracy did not improve from 0.81762 230/230 [==============================] - 27s 115ms/step - loss: 0.1472 - accuracy: 0.9566 - val_loss: 1.0879 - val_accuracy: 0.8052 Epoch 25/100 230/230 [==============================] - ETA: 0s - loss: 0.1475 - accuracy: 0.9642 Epoch 25: val_accuracy did not improve from 0.81762 230/230 [==============================] - 27s 114ms/step - loss: 0.1475 - accuracy: 0.9642 - val_loss: 1.0843 - val_accuracy: 0.8176 Epoch 26/100 230/230 [==============================] - ETA: 0s - loss: 0.0376 - accuracy: 0.9884 Epoch 26: val_accuracy improved from 0.81762 to 0.84238, saving model to best_model.h5 230/230 [==============================] - 31s 130ms/step - loss: 0.0376 - accuracy: 0.9884 - val_loss: 0.9634 - val_accuracy: 0.8424 Epoch 27/100 230/230 [==============================] - ETA: 0s - loss: 0.0112 - accuracy: 0.9981 Epoch 27: val_accuracy improved from 0.84238 to 0.85048, saving model to best_model.h5 230/230 [==============================] - 28s 118ms/step - loss: 0.0112 - accuracy: 0.9981 - val_loss: 0.9572 - val_accuracy: 0.8505 Epoch 28/100 230/230 [==============================] - ETA: 0s - loss: 0.0036 - accuracy: 0.9995 Epoch 28: val_accuracy improved from 0.85048 to 0.85238, saving model to best_model.h5 230/230 [==============================] - 27s 115ms/step - loss: 0.0036 - accuracy: 0.9995 - val_loss: 0.8783 - val_accuracy: 0.8524 Epoch 29/100 230/230 [==============================] - ETA: 0s - loss: 6.3644e-04 - accuracy: 1.0000 Epoch 29: val_accuracy improved from 0.85238 to 0.85905, saving model to best_model.h5 230/230 [==============================] - 27s 115ms/step - loss: 6.3644e-04 - accuracy: 1.0000 - val_loss: 0.8754 - val_accuracy: 0.8590 Epoch 30/100 230/230 [==============================] - ETA: 0s - loss: 4.2551e-04 - accuracy: 1.0000 Epoch 30: val_accuracy did not improve from 0.85905 230/230 [==============================] - 27s 114ms/step - loss: 4.2551e-04 - accuracy: 1.0000 - val_loss: 0.8827 - val_accuracy: 0.8590 Epoch 31/100 230/230 [==============================] - ETA: 0s - loss: 3.4693e-04 - accuracy: 1.0000 Epoch 31: val_accuracy did not improve from 0.85905 230/230 [==============================] - 28s 117ms/step - loss: 3.4693e-04 - accuracy: 1.0000 - val_loss: 0.8882 - val_accuracy: 0.8576 Epoch 32/100 230/230 [==============================] - ETA: 0s - loss: 2.9336e-04 - accuracy: 1.0000 Epoch 32: val_accuracy did not improve from 0.85905 230/230 [==============================] - 27s 114ms/step - loss: 2.9336e-04 - accuracy: 1.0000 - val_loss: 0.8941 - val_accuracy: 0.8576 Epoch 33/100 230/230 [==============================] - ETA: 0s - loss: 2.5143e-04 - accuracy: 1.0000 Epoch 33: val_accuracy did not improve from 0.85905 230/230 [==============================] - 26s 113ms/step - loss: 2.5143e-04 - accuracy: 1.0000 - val_loss: 0.9007 - val_accuracy: 0.8562 Epoch 34/100 230/230 [==============================] - ETA: 0s - loss: 2.1907e-04 - accuracy: 1.0000 Epoch 34: val_accuracy did not improve from 0.85905 230/230 [==============================] - 27s 114ms/step - loss: 2.1907e-04 - accuracy: 1.0000 - val_loss: 0.9063 - val_accuracy: 0.8562 Epoch 35/100 230/230 [==============================] - ETA: 0s - loss: 1.9236e-04 - accuracy: 1.0000 Epoch 35: val_accuracy did not improve from 0.85905 230/230 [==============================] - 28s 118ms/step - loss: 1.9236e-04 - accuracy: 1.0000 - val_loss: 0.9120 - val_accuracy: 0.8552 Epoch 36/100 230/230 [==============================] - ETA: 0s - loss: 1.6989e-04 - accuracy: 1.0000 Epoch 36: val_accuracy did not improve from 0.85905 230/230 [==============================] - 27s 114ms/step - loss: 1.6989e-04 - accuracy: 1.0000 - val_loss: 0.9174 - val_accuracy: 0.8567 Epoch 37/100 230/230 [==============================] - ETA: 0s - loss: 1.5055e-04 - accuracy: 1.0000 Epoch 37: val_accuracy did not improve from 0.85905 230/230 [==============================] - 27s 116ms/step - loss: 1.5055e-04 - accuracy: 1.0000 - val_loss: 0.9224 - val_accuracy: 0.8552 Epoch 38/100 230/230 [==============================] - ETA: 0s - loss: 1.3416e-04 - accuracy: 1.0000 Epoch 38: val_accuracy did not improve from 0.85905 230/230 [==============================] - 28s 118ms/step - loss: 1.3416e-04 - accuracy: 1.0000 - val_loss: 0.9272 - val_accuracy: 0.8548 Epoch 39/100 230/230 [==============================] - ETA: 0s - loss: 1.1958e-04 - accuracy: 1.0000 Epoch 39: val_accuracy did not improve from 0.85905 230/230 [==============================] - 31s 130ms/step - loss: 1.1958e-04 - accuracy: 1.0000 - val_loss: 0.9319 - val_accuracy: 0.8548 Epoch 39: early stopping
# Representación del loss
mostrar_graficas(entrenamiento_VGG)
#Información del modelo
modelo_VGG.summary()
Model: "model_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_2 (InputLayer) [(None, 224, 224, 3)] 0
block1_conv1 (Conv2D) (None, 224, 224, 64) 1792
block1_conv2 (Conv2D) (None, 224, 224, 64) 36928
block1_pool (MaxPooling2D) (None, 112, 112, 64) 0
block2_conv1 (Conv2D) (None, 112, 112, 128) 73856
block2_conv2 (Conv2D) (None, 112, 112, 128) 147584
block2_pool (MaxPooling2D) (None, 56, 56, 128) 0
block3_conv1 (Conv2D) (None, 56, 56, 256) 295168
block3_conv2 (Conv2D) (None, 56, 56, 256) 590080
block3_conv3 (Conv2D) (None, 56, 56, 256) 590080
block3_pool (MaxPooling2D) (None, 28, 28, 256) 0
block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160
block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808
block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808
block4_pool (MaxPooling2D) (None, 14, 14, 512) 0
block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808
block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808
block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808
block5_pool (MaxPooling2D) (None, 7, 7, 512) 0
flatten (Flatten) (None, 25088) 0
dense_2 (Dense) (None, 50) 1254450
dense_3 (Dense) (None, 20) 1020
dense_4 (Dense) (None, 21) 441
=================================================================
Total params: 15,970,599
Trainable params: 1,255,911
Non-trainable params: 14,714,688
_________________________________________________________________
# Resultados
test_loss, test_acc = modelo_VGG.evaluate(test_data)
print("\nTiempo de entrenamiento:",end_time - start_time)
print('Pérdida en el conjunto de test:', test_loss)
print('Precisión en el conjunto de test:', test_acc)
33/33 [==============================] - 8s 190ms/step - loss: 1.0031 - accuracy: 0.8610 Tiempo de entrenamiento: 1248.644618988037 Pérdida en el conjunto de test: 1.0031335353851318 Precisión en el conjunto de test: 0.8609523773193359
Una técnica frecuente, sobretodo cuando la red utilizada no es excesivamente grande (como es el caso de VGG16), para mejorar los resultados del transfer learning es el denominado fine-tunning, que consiste en reentrenar la red completa durante unas pocas épocas y con un learning rate muy pequeño.
trainable=False (no confundir con traning=False).# Definición del modelo
modelo_VGG16 = VGG16(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
# Congelamos los pesos del modelo
for layer in modelo_VGG16.layers:
layer.trainable = True
new_modelo_VGG16 = Sequential()
new_modelo_VGG16.add(modelo_VGG16)
new_modelo_VGG16.add(Flatten())
new_modelo_VGG16.add(Dense(50, activation='relu'))
new_modelo_VGG16.add(Dense(20, activation='relu'))
new_modelo_VGG16.add(Dense(21, activation='softmax'))
# Compilación de la red
optimizer = Adam(learning_rate=0.00001)
new_modelo_VGG16.compile(optimizer=optimizer, loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# Definir EarlyStopping y ModelCheckpoint
early_stopping = tf.keras.callbacks.EarlyStopping(monitor='val_accuracy', patience=10, verbose=1)
checkpoint = tf.keras.callbacks.ModelCheckpoint('best_model_ft.h5', monitor='val_accuracy', save_best_only=True, verbose=1)
# Entrenamiento
start_time = time.time()
entrenamiento_new_modelo_VGG16 = new_modelo_VGG16.fit(train_data,
epochs=10,
validation_data=val_data,
callbacks=[early_stopping, checkpoint],
verbose=1)
end_time = time.time()
Epoch 1/10 230/230 [==============================] - ETA: 0s - loss: 3.1590 - accuracy: 0.1072 Epoch 1: val_accuracy improved from -inf to 0.21810, saving model to best_model_ft.h5 230/230 [==============================] - 58s 240ms/step - loss: 3.1590 - accuracy: 0.1072 - val_loss: 2.6392 - val_accuracy: 0.2181 Epoch 2/10 230/230 [==============================] - ETA: 0s - loss: 2.2931 - accuracy: 0.3120 Epoch 2: val_accuracy improved from 0.21810 to 0.40667, saving model to best_model_ft.h5 230/230 [==============================] - 55s 237ms/step - loss: 2.2931 - accuracy: 0.3120 - val_loss: 1.9386 - val_accuracy: 0.4067 Epoch 3/10 230/230 [==============================] - ETA: 0s - loss: 1.3795 - accuracy: 0.5830 Epoch 3: val_accuracy improved from 0.40667 to 0.65762, saving model to best_model_ft.h5 230/230 [==============================] - 56s 240ms/step - loss: 1.3795 - accuracy: 0.5830 - val_loss: 1.1671 - val_accuracy: 0.6576 Epoch 4/10 230/230 [==============================] - ETA: 0s - loss: 0.7036 - accuracy: 0.7894 Epoch 4: val_accuracy improved from 0.65762 to 0.74095, saving model to best_model_ft.h5 230/230 [==============================] - 55s 236ms/step - loss: 0.7036 - accuracy: 0.7894 - val_loss: 0.9259 - val_accuracy: 0.7410 Epoch 5/10 230/230 [==============================] - ETA: 0s - loss: 0.3529 - accuracy: 0.8888 Epoch 5: val_accuracy improved from 0.74095 to 0.78905, saving model to best_model_ft.h5 230/230 [==============================] - 55s 236ms/step - loss: 0.3529 - accuracy: 0.8888 - val_loss: 0.8011 - val_accuracy: 0.7890 Epoch 6/10 230/230 [==============================] - ETA: 0s - loss: 0.1900 - accuracy: 0.9407 Epoch 6: val_accuracy improved from 0.78905 to 0.79333, saving model to best_model_ft.h5 230/230 [==============================] - 56s 239ms/step - loss: 0.1900 - accuracy: 0.9407 - val_loss: 0.9026 - val_accuracy: 0.7933 Epoch 7/10 230/230 [==============================] - ETA: 0s - loss: 0.1271 - accuracy: 0.9624 Epoch 7: val_accuracy improved from 0.79333 to 0.81952, saving model to best_model_ft.h5 230/230 [==============================] - 55s 235ms/step - loss: 0.1271 - accuracy: 0.9624 - val_loss: 0.7973 - val_accuracy: 0.8195 Epoch 8/10 230/230 [==============================] - ETA: 0s - loss: 0.0777 - accuracy: 0.9789 Epoch 8: val_accuracy improved from 0.81952 to 0.84429, saving model to best_model_ft.h5 230/230 [==============================] - 55s 236ms/step - loss: 0.0777 - accuracy: 0.9789 - val_loss: 0.7065 - val_accuracy: 0.8443 Epoch 9/10 230/230 [==============================] - ETA: 0s - loss: 0.0644 - accuracy: 0.9835 Epoch 9: val_accuracy improved from 0.84429 to 0.84952, saving model to best_model_ft.h5 230/230 [==============================] - 59s 255ms/step - loss: 0.0644 - accuracy: 0.9835 - val_loss: 0.7828 - val_accuracy: 0.8495 Epoch 10/10 230/230 [==============================] - ETA: 0s - loss: 0.0355 - accuracy: 0.9920 Epoch 10: val_accuracy improved from 0.84952 to 0.86048, saving model to best_model_ft.h5 230/230 [==============================] - 55s 237ms/step - loss: 0.0355 - accuracy: 0.9920 - val_loss: 0.7301 - val_accuracy: 0.8605
# Representación del loss
mostrar_graficas(entrenamiento_new_modelo_VGG16)
#Información del modelo
new_modelo_VGG16.summary()
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
vgg16 (Functional) (None, 7, 7, 512) 14714688
flatten_2 (Flatten) (None, 25088) 0
dense_8 (Dense) (None, 50) 1254450
dense_9 (Dense) (None, 20) 1020
dense_10 (Dense) (None, 21) 441
=================================================================
Total params: 15,970,599
Trainable params: 15,970,599
Non-trainable params: 0
_________________________________________________________________
# Resultados
test_loss, test_acc = new_modelo_VGG16.evaluate(test_data)
print("\nTiempo de entrenamiento:", end_time - start_time)
print('Pérdida en el conjunto de test:', test_loss)
print('Precisión en el conjunto de test:', test_acc)
33/33 [==============================] - 4s 94ms/step - loss: 0.8095 - accuracy: 0.8543 Tiempo de entrenamiento: 717.4674685001373 Pérdida en el conjunto de test: 0.8094838857650757 Precisión en el conjunto de test: 0.854285717010498
En este último apartado se deja libertad al alumno para conseguir, mediante el diseño de una red propia, unos mejores resultados en la tarea de clasificación.
Se valorarará la justificación de las elecciones realizadas.
# Dimensiones de entrada de los datos
input_shape = (224, 224, 3)
# Capa de entrada
input_layer = Input(shape=input_shape)
# Capa de rescalado
rescale_layer = Rescaling(scale=1./255)(input_layer)
# Bloque extractor de características
## Capa 1
conv1_layer = Conv2D(filters=32, kernel_size=(3, 3), padding='same', activation='relu')(rescale_layer)
conv2_layer = Conv2D(filters=32, kernel_size=(3, 3), padding='same', activation='relu')(conv1_layer)
pool1_layer = MaxPooling2D(pool_size=(2, 2))(conv2_layer)
## Capa 2
conv3_layer = Conv2D(filters=64, kernel_size=(3, 3), padding='same', activation='relu')(pool1_layer)
conv4_layer = Conv2D(filters=64, kernel_size=(3, 3), padding='same', activation='relu')(conv3_layer)
pool2_layer = MaxPooling2D(pool_size=(2, 2))(conv4_layer)
## Capa 3
conv5_layer = Conv2D(filters=128, kernel_size=(3, 3), padding='same', activation='relu')(pool2_layer)
conv6_layer = Conv2D(filters=128, kernel_size=(3, 3), padding='same', activation='relu')(conv5_layer)
pool3_layer = MaxPooling2D(pool_size=(2, 2))(conv6_layer)
## Capa Global
global_pool_layer = GlobalAveragePooling2D()(pool3_layer)
# Clasificador final
dense1_layer = Dense(units=512, activation='relu')(global_pool_layer)
dropout_layer = Dropout(rate=0.5)(dense1_layer)
output_layer = Dense(units=21, activation='softmax')(dropout_layer)
# Crear modelo
modelo_final = Model(inputs=input_layer, outputs=output_layer)
# Compilar el modelo
modelo_final.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# Definir EarlyStopping y ModelCheckpoint
early_stopping = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=10, verbose=1)
checkpoint = tf.keras.callbacks.ModelCheckpoint('best_model.h5', monitor='val_loss', save_best_only=True, verbose=1)
# Entrenar el modelo
start_time = time.time()
entrenamiento_modelo_final = modelo_final.fit(train_data,
epochs=100,
validation_data=val_data,
callbacks=[early_stopping, checkpoint])
end_time = time.time()
Epoch 1/100 230/230 [==============================] - ETA: 0s - loss: 3.0299 - accuracy: 0.0468 Epoch 1: val_loss improved from inf to 2.95095, saving model to best_model.h5 230/230 [==============================] - 50s 173ms/step - loss: 3.0299 - accuracy: 0.0468 - val_loss: 2.9509 - val_accuracy: 0.0767 Epoch 2/100 229/230 [============================>.] - ETA: 0s - loss: 2.6319 - accuracy: 0.1344 Epoch 2: val_loss improved from 2.95095 to 2.29867, saving model to best_model.h5 230/230 [==============================] - 30s 126ms/step - loss: 2.6317 - accuracy: 0.1350 - val_loss: 2.2987 - val_accuracy: 0.2367 Epoch 3/100 229/230 [============================>.] - ETA: 0s - loss: 2.1523 - accuracy: 0.2612 Epoch 3: val_loss improved from 2.29867 to 1.87961, saving model to best_model.h5 230/230 [==============================] - 28s 119ms/step - loss: 2.1512 - accuracy: 0.2614 - val_loss: 1.8796 - val_accuracy: 0.3843 Epoch 4/100 229/230 [============================>.] - ETA: 0s - loss: 1.8195 - accuracy: 0.3780 Epoch 4: val_loss improved from 1.87961 to 1.63593, saving model to best_model.h5 230/230 [==============================] - 29s 122ms/step - loss: 1.8199 - accuracy: 0.3780 - val_loss: 1.6359 - val_accuracy: 0.4481 Epoch 5/100 229/230 [============================>.] - ETA: 0s - loss: 1.5646 - accuracy: 0.4728 Epoch 5: val_loss improved from 1.63593 to 1.32883, saving model to best_model.h5 230/230 [==============================] - 30s 128ms/step - loss: 1.5638 - accuracy: 0.4732 - val_loss: 1.3288 - val_accuracy: 0.5586 Epoch 6/100 229/230 [============================>.] - ETA: 0s - loss: 1.3275 - accuracy: 0.5345 Epoch 6: val_loss did not improve from 1.32883 230/230 [==============================] - 28s 118ms/step - loss: 1.3278 - accuracy: 0.5347 - val_loss: 1.3628 - val_accuracy: 0.5276 Epoch 7/100 229/230 [============================>.] - ETA: 0s - loss: 1.1977 - accuracy: 0.5901 Epoch 7: val_loss improved from 1.32883 to 1.08108, saving model to best_model.h5 230/230 [==============================] - 29s 123ms/step - loss: 1.1962 - accuracy: 0.5903 - val_loss: 1.0811 - val_accuracy: 0.6467 Epoch 8/100 229/230 [============================>.] - ETA: 0s - loss: 1.0913 - accuracy: 0.6224 Epoch 8: val_loss improved from 1.08108 to 1.02929, saving model to best_model.h5 230/230 [==============================] - 29s 122ms/step - loss: 1.0910 - accuracy: 0.6226 - val_loss: 1.0293 - val_accuracy: 0.6557 Epoch 9/100 229/230 [============================>.] - ETA: 0s - loss: 0.9506 - accuracy: 0.6635 Epoch 9: val_loss improved from 1.02929 to 1.00183, saving model to best_model.h5 230/230 [==============================] - 29s 121ms/step - loss: 0.9501 - accuracy: 0.6638 - val_loss: 1.0018 - val_accuracy: 0.6581 Epoch 10/100 229/230 [============================>.] - ETA: 0s - loss: 0.9033 - accuracy: 0.6838 Epoch 10: val_loss improved from 1.00183 to 0.91614, saving model to best_model.h5 230/230 [==============================] - 29s 122ms/step - loss: 0.9023 - accuracy: 0.6838 - val_loss: 0.9161 - val_accuracy: 0.6976 Epoch 11/100 229/230 [============================>.] - ETA: 0s - loss: 0.8343 - accuracy: 0.7066 Epoch 11: val_loss improved from 0.91614 to 0.78828, saving model to best_model.h5 230/230 [==============================] - 29s 122ms/step - loss: 0.8339 - accuracy: 0.7067 - val_loss: 0.7883 - val_accuracy: 0.7414 Epoch 12/100 229/230 [============================>.] - ETA: 0s - loss: 0.8017 - accuracy: 0.7204 Epoch 12: val_loss improved from 0.78828 to 0.76631, saving model to best_model.h5 230/230 [==============================] - 28s 121ms/step - loss: 0.8007 - accuracy: 0.7208 - val_loss: 0.7663 - val_accuracy: 0.7529 Epoch 13/100 229/230 [============================>.] - ETA: 0s - loss: 0.7343 - accuracy: 0.7471 Epoch 13: val_loss improved from 0.76631 to 0.71314, saving model to best_model.h5 230/230 [==============================] - 29s 122ms/step - loss: 0.7338 - accuracy: 0.7475 - val_loss: 0.7131 - val_accuracy: 0.7700 Epoch 14/100 229/230 [============================>.] - ETA: 0s - loss: 0.6725 - accuracy: 0.7703 Epoch 14: val_loss improved from 0.71314 to 0.70099, saving model to best_model.h5 230/230 [==============================] - 29s 122ms/step - loss: 0.6728 - accuracy: 0.7703 - val_loss: 0.7010 - val_accuracy: 0.7676 Epoch 15/100 229/230 [============================>.] - ETA: 0s - loss: 0.6631 - accuracy: 0.7698 Epoch 15: val_loss improved from 0.70099 to 0.60506, saving model to best_model.h5 230/230 [==============================] - 28s 121ms/step - loss: 0.6622 - accuracy: 0.7702 - val_loss: 0.6051 - val_accuracy: 0.7967 Epoch 16/100 229/230 [============================>.] - ETA: 0s - loss: 0.6088 - accuracy: 0.7900 Epoch 16: val_loss improved from 0.60506 to 0.57974, saving model to best_model.h5 230/230 [==============================] - 28s 121ms/step - loss: 0.6086 - accuracy: 0.7901 - val_loss: 0.5797 - val_accuracy: 0.8024 Epoch 17/100 229/230 [============================>.] - ETA: 0s - loss: 0.5787 - accuracy: 0.7952 Epoch 17: val_loss did not improve from 0.57974 230/230 [==============================] - 28s 118ms/step - loss: 0.5792 - accuracy: 0.7952 - val_loss: 0.6617 - val_accuracy: 0.7819 Epoch 18/100 229/230 [============================>.] - ETA: 0s - loss: 0.5259 - accuracy: 0.8118 Epoch 18: val_loss did not improve from 0.57974 230/230 [==============================] - 33s 140ms/step - loss: 0.5255 - accuracy: 0.8120 - val_loss: 0.6086 - val_accuracy: 0.8062 Epoch 19/100 229/230 [============================>.] - ETA: 0s - loss: 0.5043 - accuracy: 0.8200 Epoch 19: val_loss did not improve from 0.57974 230/230 [==============================] - 28s 121ms/step - loss: 0.5038 - accuracy: 0.8201 - val_loss: 0.6178 - val_accuracy: 0.8029 Epoch 20/100 229/230 [============================>.] - ETA: 0s - loss: 0.5101 - accuracy: 0.8240 Epoch 20: val_loss did not improve from 0.57974 230/230 [==============================] - 29s 122ms/step - loss: 0.5102 - accuracy: 0.8241 - val_loss: 0.6056 - val_accuracy: 0.8190 Epoch 21/100 229/230 [============================>.] - ETA: 0s - loss: 0.4868 - accuracy: 0.8289 Epoch 21: val_loss did not improve from 0.57974 230/230 [==============================] - 29s 122ms/step - loss: 0.4867 - accuracy: 0.8288 - val_loss: 0.6139 - val_accuracy: 0.8071 Epoch 22/100 229/230 [============================>.] - ETA: 0s - loss: 0.4640 - accuracy: 0.8383 Epoch 22: val_loss improved from 0.57974 to 0.51141, saving model to best_model.h5 230/230 [==============================] - 28s 120ms/step - loss: 0.4638 - accuracy: 0.8382 - val_loss: 0.5114 - val_accuracy: 0.8424 Epoch 23/100 229/230 [============================>.] - ETA: 0s - loss: 0.4082 - accuracy: 0.8563 Epoch 23: val_loss did not improve from 0.51141 230/230 [==============================] - 33s 143ms/step - loss: 0.4081 - accuracy: 0.8559 - val_loss: 0.5660 - val_accuracy: 0.8224 Epoch 24/100 229/230 [============================>.] - ETA: 0s - loss: 0.4355 - accuracy: 0.8506 Epoch 24: val_loss did not improve from 0.51141 230/230 [==============================] - 29s 121ms/step - loss: 0.4346 - accuracy: 0.8509 - val_loss: 0.5882 - val_accuracy: 0.8143 Epoch 25/100 229/230 [============================>.] - ETA: 0s - loss: 0.4035 - accuracy: 0.8581 Epoch 25: val_loss did not improve from 0.51141 230/230 [==============================] - 28s 119ms/step - loss: 0.4035 - accuracy: 0.8582 - val_loss: 0.5619 - val_accuracy: 0.8333 Epoch 26/100 229/230 [============================>.] - ETA: 0s - loss: 0.3745 - accuracy: 0.8704 Epoch 26: val_loss improved from 0.51141 to 0.48655, saving model to best_model.h5 230/230 [==============================] - 28s 121ms/step - loss: 0.3741 - accuracy: 0.8705 - val_loss: 0.4866 - val_accuracy: 0.8600 Epoch 27/100 229/230 [============================>.] - ETA: 0s - loss: 0.3608 - accuracy: 0.8724 Epoch 27: val_loss improved from 0.48655 to 0.44667, saving model to best_model.h5 230/230 [==============================] - 28s 121ms/step - loss: 0.3600 - accuracy: 0.8728 - val_loss: 0.4467 - val_accuracy: 0.8595 Epoch 28/100 229/230 [============================>.] - ETA: 0s - loss: 0.3509 - accuracy: 0.8777 Epoch 28: val_loss did not improve from 0.44667 230/230 [==============================] - 28s 121ms/step - loss: 0.3515 - accuracy: 0.8776 - val_loss: 0.5956 - val_accuracy: 0.8229 Epoch 29/100 229/230 [============================>.] - ETA: 0s - loss: 0.3151 - accuracy: 0.8911 Epoch 29: val_loss did not improve from 0.44667 230/230 [==============================] - 28s 121ms/step - loss: 0.3147 - accuracy: 0.8912 - val_loss: 0.5146 - val_accuracy: 0.8510 Epoch 30/100 229/230 [============================>.] - ETA: 0s - loss: 0.3002 - accuracy: 0.8955 Epoch 30: val_loss did not improve from 0.44667 230/230 [==============================] - 28s 120ms/step - loss: 0.2998 - accuracy: 0.8955 - val_loss: 0.5361 - val_accuracy: 0.8486 Epoch 31/100 229/230 [============================>.] - ETA: 0s - loss: 0.2834 - accuracy: 0.9041 Epoch 31: val_loss did not improve from 0.44667 230/230 [==============================] - 29s 122ms/step - loss: 0.2838 - accuracy: 0.9038 - val_loss: 0.5531 - val_accuracy: 0.8210 Epoch 32/100 229/230 [============================>.] - ETA: 0s - loss: 0.2841 - accuracy: 0.9028 Epoch 32: val_loss did not improve from 0.44667 230/230 [==============================] - 29s 125ms/step - loss: 0.2841 - accuracy: 0.9030 - val_loss: 0.4708 - val_accuracy: 0.8614 Epoch 33/100 229/230 [============================>.] - ETA: 0s - loss: 0.2878 - accuracy: 0.8978 Epoch 33: val_loss improved from 0.44667 to 0.42972, saving model to best_model.h5 230/230 [==============================] - 31s 134ms/step - loss: 0.2875 - accuracy: 0.8981 - val_loss: 0.4297 - val_accuracy: 0.8714 Epoch 34/100 229/230 [============================>.] - ETA: 0s - loss: 0.2530 - accuracy: 0.9102 Epoch 34: val_loss improved from 0.42972 to 0.39075, saving model to best_model.h5 230/230 [==============================] - 34s 143ms/step - loss: 0.2527 - accuracy: 0.9103 - val_loss: 0.3908 - val_accuracy: 0.8862 Epoch 35/100 229/230 [============================>.] - ETA: 0s - loss: 0.2572 - accuracy: 0.9083 Epoch 35: val_loss did not improve from 0.39075 230/230 [==============================] - 33s 141ms/step - loss: 0.2570 - accuracy: 0.9083 - val_loss: 0.5409 - val_accuracy: 0.8305 Epoch 36/100 229/230 [============================>.] - ETA: 0s - loss: 0.2424 - accuracy: 0.9162 Epoch 36: val_loss did not improve from 0.39075 230/230 [==============================] - 31s 130ms/step - loss: 0.2429 - accuracy: 0.9161 - val_loss: 0.3995 - val_accuracy: 0.8852 Epoch 37/100 229/230 [============================>.] - ETA: 0s - loss: 0.2216 - accuracy: 0.9207 Epoch 37: val_loss did not improve from 0.39075 230/230 [==============================] - 29s 122ms/step - loss: 0.2211 - accuracy: 0.9210 - val_loss: 0.4551 - val_accuracy: 0.8681 Epoch 38/100 229/230 [============================>.] - ETA: 0s - loss: 0.2204 - accuracy: 0.9221 Epoch 38: val_loss did not improve from 0.39075 230/230 [==============================] - 30s 127ms/step - loss: 0.2199 - accuracy: 0.9223 - val_loss: 0.4085 - val_accuracy: 0.8829 Epoch 39/100 229/230 [============================>.] - ETA: 0s - loss: 0.2217 - accuracy: 0.9219 Epoch 39: val_loss improved from 0.39075 to 0.35526, saving model to best_model.h5 230/230 [==============================] - 31s 130ms/step - loss: 0.2217 - accuracy: 0.9219 - val_loss: 0.3553 - val_accuracy: 0.8971 Epoch 40/100 229/230 [============================>.] - ETA: 0s - loss: 0.2233 - accuracy: 0.9249 Epoch 40: val_loss did not improve from 0.35526 230/230 [==============================] - 31s 134ms/step - loss: 0.2238 - accuracy: 0.9246 - val_loss: 0.4069 - val_accuracy: 0.8905 Epoch 41/100 229/230 [============================>.] - ETA: 0s - loss: 0.1809 - accuracy: 0.9367 Epoch 41: val_loss did not improve from 0.35526 230/230 [==============================] - 28s 120ms/step - loss: 0.1805 - accuracy: 0.9367 - val_loss: 0.3897 - val_accuracy: 0.8967 Epoch 42/100 229/230 [============================>.] - ETA: 0s - loss: 0.1863 - accuracy: 0.9370 Epoch 42: val_loss did not improve from 0.35526 230/230 [==============================] - 28s 121ms/step - loss: 0.1862 - accuracy: 0.9369 - val_loss: 0.4940 - val_accuracy: 0.8690 Epoch 43/100 229/230 [============================>.] - ETA: 0s - loss: 0.1702 - accuracy: 0.9397 Epoch 43: val_loss did not improve from 0.35526 230/230 [==============================] - 28s 121ms/step - loss: 0.1703 - accuracy: 0.9395 - val_loss: 0.4771 - val_accuracy: 0.8914 Epoch 44/100 229/230 [============================>.] - ETA: 0s - loss: 0.1883 - accuracy: 0.9391 Epoch 44: val_loss did not improve from 0.35526 230/230 [==============================] - 28s 121ms/step - loss: 0.1887 - accuracy: 0.9389 - val_loss: 0.3675 - val_accuracy: 0.8995 Epoch 45/100 229/230 [============================>.] - ETA: 0s - loss: 0.1768 - accuracy: 0.9385 Epoch 45: val_loss did not improve from 0.35526 230/230 [==============================] - 29s 122ms/step - loss: 0.1764 - accuracy: 0.9385 - val_loss: 0.4906 - val_accuracy: 0.8852 Epoch 46/100 229/230 [============================>.] - ETA: 0s - loss: 0.1829 - accuracy: 0.9365 Epoch 46: val_loss did not improve from 0.35526 230/230 [==============================] - 28s 119ms/step - loss: 0.1833 - accuracy: 0.9365 - val_loss: 0.4830 - val_accuracy: 0.8771 Epoch 47/100 229/230 [============================>.] - ETA: 0s - loss: 0.1516 - accuracy: 0.9481 Epoch 47: val_loss did not improve from 0.35526 230/230 [==============================] - 29s 121ms/step - loss: 0.1512 - accuracy: 0.9483 - val_loss: 0.4557 - val_accuracy: 0.8871 Epoch 48/100 229/230 [============================>.] - ETA: 0s - loss: 0.1512 - accuracy: 0.9471 Epoch 48: val_loss did not improve from 0.35526 230/230 [==============================] - 28s 121ms/step - loss: 0.1512 - accuracy: 0.9469 - val_loss: 0.3762 - val_accuracy: 0.9038 Epoch 49/100 229/230 [============================>.] - ETA: 0s - loss: 0.1552 - accuracy: 0.9475 Epoch 49: val_loss did not improve from 0.35526 230/230 [==============================] - 28s 121ms/step - loss: 0.1555 - accuracy: 0.9473 - val_loss: 0.5175 - val_accuracy: 0.8752 Epoch 49: early stopping
# Representación del loss
mostrar_graficas(entrenamiento_modelo_final)
#Información del modelo
modelo_final.summary()
Model: "model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) [(None, 224, 224, 3)] 0
rescaling (Rescaling) (None, 224, 224, 3) 0
conv2d (Conv2D) (None, 224, 224, 32) 896
conv2d_1 (Conv2D) (None, 224, 224, 32) 9248
max_pooling2d (MaxPooling2D (None, 112, 112, 32) 0
)
conv2d_2 (Conv2D) (None, 112, 112, 64) 18496
conv2d_3 (Conv2D) (None, 112, 112, 64) 36928
max_pooling2d_1 (MaxPooling (None, 56, 56, 64) 0
2D)
conv2d_4 (Conv2D) (None, 56, 56, 128) 73856
conv2d_5 (Conv2D) (None, 56, 56, 128) 147584
max_pooling2d_2 (MaxPooling (None, 28, 28, 128) 0
2D)
global_average_pooling2d (G (None, 128) 0
lobalAveragePooling2D)
dense (Dense) (None, 512) 66048
dropout (Dropout) (None, 512) 0
dense_1 (Dense) (None, 21) 10773
=================================================================
Total params: 363,829
Trainable params: 363,829
Non-trainable params: 0
_________________________________________________________________
# Estadísticas y resultados del modelo
test_loss, test_acc = modelo_final.evaluate(test_data)
print("\nTiempo de entrenamiento:", end_time - start_time)
print('Pérdida en el conjunto de test:', test_loss)
print('Precisión en el conjunto de test:', test_acc)
33/33 [==============================] - 6s 132ms/step - loss: 0.4912 - accuracy: 0.8695 Tiempo de entrenamiento: 1600.0847635269165 Pérdida en el conjunto de test: 0.491167813539505 Precisión en el conjunto de test: 0.869523823261261